iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

JUnit

JUnit 5 (Jupiter): the modern Java test framework. Annotations, parameterised tests, lifecycle, assertions, extensions.

Java — JUnit 5

EXAMPLE
// ===== Setup (Maven) =====
// pom.xml
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.10.2</version>
    <scope>test</scope>
</dependency>

// ===== Basic test =====
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class MathTest {
    @Test
    void onePlusOne() {
        assertEquals(2, 1 + 1);
    }
}

// Run: mvn test or gradle test

// ===== Annotations =====
// @Test               regular test
// @DisplayName        human-readable label
// @BeforeEach         runs before each test
// @AfterEach          runs after each test
// @BeforeAll          runs once before all tests (static)
// @AfterAll           runs once after all tests (static)
// @Disabled           skip
// @Nested             nested test class
// @Tag("slow")        group + filter

@DisplayName("User service")
class UserServiceTest {
    UserService svc;

    @BeforeEach
    void setUp() {
        svc = new UserService(new InMemoryRepo());
    }

    @Test
    @DisplayName("creates new user")
    void createsUser() {
        var user = svc.create("Alex");
        assertNotNull(user.id());
        assertEquals("Alex", user.name());
    }
}

// ===== Assertions =====
assertEquals(expected, actual);
assertEquals(expected, actual, "helpful message");
assertNotEquals(2, 3);
assertTrue(condition);
assertFalse(condition);
assertNull(value);
assertNotNull(value);
assertSame(o1, o2);     // reference equality
assertArrayEquals(new int[]{1,2,3}, result);

// Iterables:
assertIterableEquals(List.of(1, 2, 3), result);

// Multiple assertions in one test:
assertAll("user",
    () -> assertEquals("Alex", user.name()),
    () -> assertNotNull(user.id())
);

// Exceptions:
var ex = assertThrows(IllegalArgumentException.class, () -> svc.create(null));
assertEquals("name required", ex.getMessage());

// Timeouts:
assertTimeout(Duration.ofSeconds(1), () -> longOp());
assertTimeoutPreemptively(Duration.ofMillis(500), () -> blockingOp());

// ===== Parameterised tests =====
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;

class ParityTest {
    @ParameterizedTest
    @ValueSource(ints = {2, 4, 6, 8})
    void allEven(int n) {
        assertEquals(0, n % 2);
    }

    @ParameterizedTest
    @CsvSource({
        "1, 2, 3",
        "4, 5, 9",
    })
    void adds(int a, int b, int expected) {
        assertEquals(expected, a + b);
    }

    static Stream<Arguments> data() {
        return Stream.of(
            arguments("a", 1),
            arguments("b", 2)
        );
    }

    @ParameterizedTest
    @MethodSource("data")
    void parametricFromMethod(String name, int n) { /* ... */ }
}

// ===== Nested tests =====
class CartTest {
    @Nested class WhenEmpty {
        @Test void totalIsZero() { /* ... */ }
    }
    @Nested class WhenHasItems {
        @Test void totalSums() { /* ... */ }
    }
}

// ===== Mocking (Mockito) =====
import org.mockito.Mockito;
import static org.mockito.Mockito.*;

@Test
void usesRepo() {
    var repo = mock(UserRepo.class);
    when(repo.findById(1)).thenReturn(new User(1, "Alex"));
    var svc = new UserService(repo);
    assertEquals("Alex", svc.greet(1));
    verify(repo).findById(1);
}

// ===== Extensions =====
// Custom behaviour via @ExtendWith. Spring Boot has @SpringBootTest.

// ===== Patterns =====
// - One test class per production class
// - @Nested for grouping by scenario
// - assertAll for multi-property checks
// - assertThrows for error testing
// - Parameterised tests for boundary conditions

// ===== Pitfalls =====
// - Static state across tests -> flaky tests
// - Test order assumptions (do not rely on it)
// - Heavy @BeforeAll with shared state
// - Mocking the class under test instead of its dependencies

Why it matters

JUnit 5 is the modern Java test framework. @Test, @DisplayName, @ParameterizedTest, @Nested, assertAll, assertThrows. Pair with Mockito for mocks. Keep tests independent, label them well, parameterise for breadth, and the suite stays maintainable as the codebase grows.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
@Test
void addsNumbers() {
    assertEquals(5, calc.add(2, 3));
}
Try it Yourself »

Discussion

Loading…