JUnit5 Assertions

Basic Assertions

import static org.junit.jupiter.api.Assertions.*; @Test void basicAssertions() { // Equality assertEquals(4, 2 + 2); assertEquals("hello", result.toLowerCase()); assertEquals(3.14, Math.PI, 0.01); // delta for doubles // Null checks assertNull(user.getMiddleName()); assertNotNull(response.getBody()); // Boolean assertTrue(list.isEmpty()); assertFalse(user.isBanned()); // Reference equality assertSame(singleton, Singleton.getInstance()); assertNotSame(obj1, obj2); // Array equality (deep) assertArrayEquals(new int[]{1, 2, 3}, actual); // Iterable equality assertIterableEquals(List.of("a", "b"), result); // With failure message (last param or supplier) assertEquals(200, response.getStatus(), "Expected OK status"); assertTrue(predicate, () -> "Computed message: " + computeExpected()); }

assertThrows & assertDoesNotThrow

@Test void exceptionAssertions() { // Assert specific exception is thrown IllegalArgumentException ex = assertThrows( IllegalArgumentException.class, () -> service.create(null) ); assertEquals("Name cannot be null", ex.getMessage()); // Assert exception type and cause RuntimeException wrapped = assertThrows(RuntimeException.class, () -> service.callExternal()); assertInstanceOf(IOException.class, wrapped.getCause()); // Assert NO exception is thrown assertDoesNotThrow(() -> service.healthCheck()); // assertThrowsExactly — no subclasses assertThrowsExactly( NullPointerException.class, () -> parseNull() ); }

assertAll — Grouped Assertions

@Test void userFieldsAreCorrect() { User user = service.findById(1L); // All assertions execute even if one fails assertAll("user properties", () -> assertEquals("Alice", user.getName()), () -> assertEquals("[email protected]", user.getEmail()), () -> assertTrue(user.isActive()), () -> assertNotNull(user.getCreatedAt()) ); } // Nested assertAll @Test void addressIsValid() { Address address = user.getAddress(); assertAll("full address check", () -> assertAll("street", () -> assertNotNull(address.getStreet()), () -> assertFalse(address.getStreet().isBlank()) ), () -> assertNotNull(address.getCity()), () -> assertEquals(5, address.getZipCode().length()) ); }

assertTimeout & assertTimeoutPreemptively

import java.time.Duration; @Test void operationCompletesInTime() { // Fails if execution exceeds duration (waits for completion) String result = assertTimeout(Duration.ofSeconds(2), () -> { return processBigFile(); }); assertNotNull(result); } @Test void operationAbortedIfTooSlow() { // Interrupts execution if duration exceeded (different thread) assertTimeoutPreemptively(Duration.ofMillis(500), () -> { Thread.sleep(200); // This would fail if changed to 600 return fetchData(); }); } // Note: assertTimeout uses same thread (ThreadLocal state works) // assertTimeoutPreemptively uses new thread (ThreadLocal state lost)

Assumptions — assumeTrue / assumingThat

import static org.junit.jupiter.api.Assumptions.*; @Test void onlyRunOnLinux() { assumeTrue("Linux".equals(System.getProperty("os.name"))); // Test only runs on Linux, skipped otherwise (not failed) } @Test void onlyRunWithRealDatabase() { assumeTrue(System.getenv("USE_REAL_DB") != null, "Skipping: USE_REAL_DB env var not set"); // ... } @Test void conditionalBehavior() { assumingThat( Boolean.getBoolean("ci.build"), () -> { // Only runs in CI assertEquals(0, getWarnings().size()); } ); // This always runs: assertNotNull(mainResult); }

Custom Assertions with AssertJ

// Add AssertJ for fluent, readable assertions // Maven: org.assertj:assertj-core:3.x import static org.assertj.core.api.Assertions.*; @Test void assertJExamples() { // Strings assertThat("Hello World") .startsWith("Hello") .containsIgnoringCase("world") .hasSize(11); // Collections assertThat(list) .hasSize(3) .contains("apple", "banana") .doesNotContain("cherry"); // Objects assertThat(user) .extracting("name", "email") .containsExactly("Alice", "[email protected]"); // Exceptions assertThatThrownBy(() -> service.divide(1, 0)) .isInstanceOf(ArithmeticException.class) .hasMessage("/ by zero"); // Numbers assertThat(price).isBetween(9.99, 29.99); }