Lesson 25 / 35
JUnit 5 In Depth
Use JUnit 5 assertions such as assertThrows and assertAll, and control setup and teardown with 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.
@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.
@ParameterizedTest
@CsvSource({"2,4", "3,9", "5,25"})
void squares(int in, int expected) {
assertEquals(expected, MathUtil.square(in));
}