jUnit
AssertContains
testing
Java
unit testing

AssertContains on strings in jUnit

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

JUnit does not ship a built-in assertContains method for strings. The normal pattern is to assert that actual.contains(expected) is true, or to use a richer assertion library such as AssertJ or Hamcrest if you want more expressive failure messages. The important part is choosing an assertion style that keeps test failures readable.

Use assertTrue with String.contains

The simplest JUnit-only version is:

java
1import static org.junit.jupiter.api.Assertions.assertTrue;
2
3import org.junit.jupiter.api.Test;
4
5class MessageTest {
6    @Test
7    void responseContainsId() {
8        String response = "Created order with id=42";
9
10        assertTrue(response.contains("id=42"));
11    }
12}

This is perfectly valid. It keeps the dependency list small and works well for many tests.

The weakness is not correctness. The weakness is failure output. If the assertion fails, the message may be less descriptive than a purpose-built string assertion.

Add a Helpful Failure Message

When substring checks are central to the test, include a message that shows what was expected.

java
1import static org.junit.jupiter.api.Assertions.assertTrue;
2
3import org.junit.jupiter.api.Test;
4
5class MessageTest {
6    @Test
7    void responseContainsId() {
8        String response = "Created order with id=42";
9
10        assertTrue(
11            response.contains("id=42"),
12            () -> "Expected substring id=42 in response: " + response
13        );
14    }
15}

The supplier form keeps the message lazy and makes failures much easier to diagnose.

Guard Against Null Explicitly

If the source string could be null, do not hide that inside a boolean expression. Assert the null expectation first so the failure tells you what actually went wrong.

java
1import static org.junit.jupiter.api.Assertions.assertNotNull;
2import static org.junit.jupiter.api.Assertions.assertTrue;
3
4import org.junit.jupiter.api.Test;
5
6class MessageTest {
7    @Test
8    void responseContainsToken() {
9        String response = getResponse();
10
11        assertNotNull(response, "response should not be null");
12        assertTrue(response.contains("token"));
13    }
14
15    private String getResponse() {
16        return "token=abc123";
17    }
18}

This is clearer than writing response != null && response.contains("token") inside one assertion.

Prefer Richer Assertion Libraries When Readability Matters

If your project already uses AssertJ or Hamcrest, string containment becomes more readable.

With AssertJ:

java
1import static org.assertj.core.api.Assertions.assertThat;
2
3import org.junit.jupiter.api.Test;
4
5class MessageTest {
6    @Test
7    void responseContainsId() {
8        String response = "Created order with id=42";
9
10        assertThat(response).contains("id=42");
11    }
12}

This reads closer to English and usually produces better failure messages. JUnit is still the test runner here; AssertJ is just providing richer assertions.

Handle Case Sensitivity Deliberately

A raw contains check is case-sensitive. If that is not what you want, normalize both sides or use an assertion library feature that says so explicitly.

java
1import static org.junit.jupiter.api.Assertions.assertTrue;
2
3import java.util.Locale;
4import org.junit.jupiter.api.Test;
5
6class MessageTest {
7    @Test
8    void responseContainsSubstringIgnoringCase() {
9        String response = "Order Status: Completed";
10        String expected = "status: completed";
11
12        assertTrue(
13            response.toLowerCase(Locale.ROOT).contains(expected.toLowerCase(Locale.ROOT))
14        );
15    }
16}

Using Locale.ROOT avoids locale-dependent casing surprises.

Consider Whether Containment Is the Right Check

Sometimes people reach for a substring assertion when they really want:

  • equality
  • a prefix or suffix check
  • a regex or pattern match
  • structured data validation such as JSON parsing

For example, if the response is JSON, checking contains("\"status\":\"ok\"") is usually weaker than parsing the JSON and asserting the actual field value.

So use containment when the test intent is genuinely about substring presence, not because it is the fastest thing to type.

Common Pitfalls

  • Assuming JUnit has a built-in assertContains for strings.
  • Hiding null checks inside one large boolean expression.
  • Writing containment assertions for structured payloads that should be parsed instead.
  • Forgetting that String.contains is case-sensitive.
  • Choosing a weak failure message that makes debugging harder than necessary.

Summary

  • JUnit itself does not provide a dedicated string assertContains.
  • The standard JUnit approach is assertTrue(actual.contains(expected)).
  • Add clear failure messages and separate null assertions when needed.
  • AssertJ or Hamcrest can make containment tests more expressive.
  • Use substring assertions only when substring presence is truly the behavior you want to test.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.