Test strategymedium0-2 years
A service has 800 unit tests that run in 4 seconds and 40 browser tests that take 25 minutes, and nothing in between. A repository query with a wrong `JOIN` shipped and was caught only by a browser test, three hours after the merge. Name the shape, explain why the unit tests could not have caught it, and say where you would add tests.
That is the hourglass: many unit tests, many end-to-end tests, nothing in the middle. A unit test of a repository mocks the database or never reaches it, so it cannot tell whether the SQL is valid or returns the right rows; only a database can say that. The missing layer is integration: a @DataJpaTest against a real PostgreSQL in a container, which runs in seconds and fails on the exact query. The rule for placing a test is 'the lowest level that could actually fail for this reason': a discount threshold is a unit test, a query is an integration test against a real database, and 'can a customer check out' is one end-to-end test, not forty.
PreviousIn one JUnit 5 test class, `rejectsDuplicateEmail` passes when run on its own and fails when the whole class runs. The class keeps a `static List<Customer> saved` for its in-memory repository, and last week someone added `@TestInstance(Lifecycle.PER_CLASS)` so a `@BeforeAll` method could stop being static. Explain the Jupiter lifecycle rule these two changes work against, and how you would fix the class.Next After a refactor, twelve tests fail with `UnnecessaryStubbingException` even though no assertion changed. A teammate proposes `@MockitoSettings(strictness = Strictness.LENIENT)` on the base class. What is Mockito telling you, why is lenient the wrong default, and what do these failures usually reveal about the tests?