Assertions and Lifecycle

Assertions

AssertionChecks
assertEquals(expected, actual)equality (assertEquals(0.1, x, 1e-9) for doubles)
assertTrue / assertFalsecondition
assertNull / assertNotNullnull-ness
assertThrows(Type.class, () -> ...)an exception is thrown; returns it
assertAll(...)run several assertions, report all failures
assertIterableEquals, assertArrayEqualscollections / arrays
assertTimeout(Duration, ...)finishes in time

Tip: Many teams prefer AssertJ for readable fluent assertions: assertThat(order.items()).hasSize(2).extracting(Item::name).containsExactly("Pen", "Book");

Lifecycle Annotations

class CartTest {
    private Cart cart;

    @BeforeAll static void startOnce()   { /* expensive shared setup, e.g. test container */ }
    @BeforeEach void setUp()             { cart = new Cart(); }          // fresh object for every test
    @AfterEach  void tearDown()          { /* clean temp files */ }
    @AfterAll   static void stopOnce()   { }

    @Test
    void newCartIsEmpty() {
        assertAll(
                () -> assertEquals(0, cart.size()),
                () -> assertEquals(0.0, cart.total()));
    }

    @Test
    void addingItemIncreasesTotal() {
        cart.add(new Item("Pen", 20), 3);
        assertEquals(60.0, cart.total());
    }

    @Test @Disabled("waiting for coupon service") void appliesCoupon() { }

    @Nested
    class WhenCartHasItems {
        @BeforeEach void addItem() { cart.add(new Item("Bag", 899), 1); }
        @Test void removeMakesItEmpty() { cart.remove("Bag"); assertEquals(0, cart.size()); }
    }
}

Note: JUnit creates a new instance of the test class for every test method, so tests do not share state through fields. Tests must not depend on each other's order.

Arrange–Act–Assert

Structure every test in three parts: Arrange (set up data), Act (call the method once), Assert (check the result). Name tests after behaviour: shouldRejectExpiredCoupon(), transfer_failsWhenBalanceTooLow().