# Writing Your First Tests — JUnit 5 & Mockito

Source: https://www.skillbyai.com/en/java-testing/f-first

> Structure tests with arrange-act-assert and clear names.

## Small, focused, readable tests

A JUnit Jupiter test is a method annotated with **`@Test`** in a test class; neither needs to be `public`. Each test should check **one behaviour** and follow the **arrange-act-assert** (AAA) structure, also called **given-when-then**: set up inputs and objects, call the method under test, then verify the result. Name tests so a failure explains itself, such as `withdrawFailsWhenBalanceIsInsufficient`, or use **`@DisplayName`** for readable sentences. Use assertions from `org.junit.jupiter.api.Assertions` (`assertEquals(expected, actual)`, `assertTrue`, `assertThrows`) or the fluent **AssertJ** library (`assertThat(actual).isEqualTo(expected)`). Remember argument order in JUnit: **expected first, then actual**, otherwise failure messages are misleading. Keep tests independent: never rely on another test having run first, and create fresh objects in each test. Run them from the IDE, with `mvn test` or with `gradle test`, ideally on every save and in CI for every change.

## Arrange, act, assert

One behaviour per test, readable names and expected-before-actual.

```java
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class WalletTest {

    @Test
    @DisplayName("paying less than the balance reduces it by the amount")
    void payReducesBalance() {
        // arrange
        Wallet wallet = new Wallet(1_000);
        // act
        wallet.pay(300);
        // assert
        assertEquals(700, wallet.balance());
    }

    @Test
    void payingMoreThanBalanceThrowsAndLeavesBalanceUnchanged() {
        Wallet wallet = new Wallet(200);

        InsufficientFundsException ex =
            assertThrows(InsufficientFundsException.class, () -> wallet.pay(500));

        assertEquals("requested 500 but only 200 available", ex.getMessage());
        assertEquals(200, wallet.balance());
    }
}

// mvn test          or          ./gradlew test
```

## Make the failure message do the work

A test named `test1` failing with "expected 700 but was 1000" sends you hunting. A test named `payReducesBalance` tells you which rule broke before you open the file.

**Quiz:** In JUnit's assertEquals, what is the conventional argument order?

- [ ] actual, expected
- [ ] message, actual
- [x] expected, actual
- [ ] Any order; it makes no difference to the output

*Answer:* expected, actual. JUnit expects the expected value first; reversing them produces confusing failure messages.
