# JUnit 5 In Depth — Advanced Java

Source: https://www.geekswithgeeks.com/en/advanced-java/adv-junit5-deep

> Use the full assertion toolkit — assertEquals, assertThrows, assertAll — and control setup/teardown per test and per class with JUnit 5's lifecycle annotations.

## Lifecycle annotations

`@BeforeEach`/`@AfterEach` run around **every** test method (fresh state, no leakage between tests); `@BeforeAll`/`@AfterAll` run **once** for the whole class and must be `static` (unless the class uses `@TestInstance(PER_CLASS)`). Use `@BeforeAll` only for expensive, read-only setup shared safely across tests.

## assertAll and assertThrows

`assertAll` groups related assertions so **all** of them run and report even if an earlier one fails — a single `assertEquals` would stop at the first failure. `assertThrows` verifies a specific exception type and lets you inspect its message.

```java
@Test
void orderValidation() {
    Order o = new Order(-5, "");
    assertAll(
        () -> assertTrue(o.hasErrors()),
        () -> assertEquals(2, o.errorCount())
    );

    var ex = assertThrows(IllegalArgumentException.class,
        () -> new Order(-1, "x"));
    assertTrue(ex.getMessage().contains("quantity"));
}
```

## Parameterized tests

`@ParameterizedTest` with `@ValueSource`, `@CsvSource`, or `@MethodSource` runs the same test body once per input, replacing copy-pasted near-identical `@Test` methods.

```java
@ParameterizedTest
@CsvSource({"2,4", "3,9", "5,25"})
void squares(int in, int expected) {
    assertEquals(expected, MathUtil.square(in));
}
```
