# Why Automated Tests — JUnit 5 & Mockito

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

> Explain what unit tests are for and where they sit in a testing strategy.

## Confidence to change code

An **automated test** is code that runs your code and checks the result. Its real value is **confidence**: you can refactor, upgrade libraries or accept a teammate's change knowing that important behaviour still works, and you find mistakes in seconds instead of in production. A **unit test** checks a small piece of behaviour (usually a class or a few collaborating classes) in isolation, quickly and deterministically, with no network, real database or clock. **Integration tests** check that pieces work together, such as a repository against a real database or a controller with the web layer. **End-to-end tests** drive the whole system. The **test pyramid** recommends many fast unit tests, fewer integration tests and very few end-to-end tests, because lower tests are faster and pinpoint failures better. Good tests are **fast**, **isolated** (no shared state between tests), **repeatable** (same result every run), **self-checking** (pass or fail automatically) and **timely** (written with the code), often summarised as FIRST. In Java, **JUnit** runs tests and **Mockito** replaces collaborators with test doubles.

## The test pyramid

Many fast unit tests at the base, fewer integration tests, very few slow end-to-end tests.

![A pyramid divided into three horizontal bands: a wide base of many small squares, a middle band with fewer, and a narrow top with a couple.](assets/figures/java-testing/section-1-map.svg) — Figure 1.1 — Unit, integration and end-to-end tests in proportion.

## What a unit test protects

A tiny rule and the test that guards it.

```java
public final class ShippingCalculator {
    public long feePaise(long orderTotalPaise, boolean express) {
        if (orderTotalPaise >= 100_000) return 0;          // free above Rs 1000
        return express ? 9_900 : 4_900;
    }
}

class ShippingCalculatorTest {
    private final ShippingCalculator calc = new ShippingCalculator();

    @Test
    void freeShippingAtOrAboveThreshold() {
        assertEquals(0, calc.feePaise(100_000, true));
    }

    @Test
    void expressCostsMoreBelowThreshold() {
        assertEquals(9_900, calc.feePaise(99_999, true));
        assertEquals(4_900, calc.feePaise(99_999, false));
    }
}
```

## Test behaviour, not lines

Aim tests at the rules your code promises (free shipping at Rs 1000) rather than at how it is implemented. Behaviour-focused tests survive refactoring; implementation-focused tests break whenever the code is tidied.

**Quiz:** Which property is part of the FIRST principles for good unit tests?

- [x] Repeatable
- [ ] Flaky
- [ ] Remote
- [ ] Sequential only

*Answer:* Repeatable. FIRST stands for Fast, Isolated, Repeatable, Self-checking and Timely.
