Memra

Testing with JUnit 5

@Test, core assertions, @BeforeEach, arrange-act-assert, and why unit tests exist.

Why unit tests?

A unit test isolates one piece of behaviour and asserts it is correct. Tests give you:

- Confidence to refactor: if the tests pass, behaviour is preserved. - Executable documentation: tests show how a class is supposed to be used. - Fast regression feedback: run mvn test after every change; failures surface immediately.

JUnit 5 (the JUnit Jupiter API) is the standard Java testing library.

Anatomy of a test class

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
    private Calculator calc;

    @BeforeEach
    void setUp() {
        calc = new Calculator();   // fresh instance before each test
    }

    @Test
    void add_returnsSum() {
        // Arrange
        int a = 3, b = 4;
        // Act
        int result = calc.add(a, b);
        // Assert
        assertEquals(7, result);
    }

    @Test
    void divide_byZero_throwsArithmeticException() {
        assertThrows(ArithmeticException.class, () -> calc.divide(5, 0));
    }
}

Arrange-Act-Assert (AAA) is the standard structure for a readable test:

- Arrange: set up the objects and inputs. - Act: call the method under test. - Assert: verify the outcome.

Core assertions

| Assertion | Tests | |---|---| | assertEquals(expected, actual) | Value equality | | assertNotEquals(a, b) | Values differ | | assertTrue(condition) | Condition is true | | assertFalse(condition) | Condition is false | | assertNull(obj) | Reference is null | | assertNotNull(obj) | Reference is not null | | assertThrows(ExType.class, () -> ...) | Lambda throws that exception |

Note the argument order: expected first, actual second. @BeforeEach methods run before every @Test method, resetting shared state so tests don't interfere with each other.

NORMAL ~/memra/learn/java-from-zero/junit5-testing utf-8 LF