18 · Testing the complete backend / LESSON 88 OF 102
JUnit lifecycle and parameterized tests
A test should expose a specific defect through a precise observable assertion.
Before this lesson: Version the database schema
Understand the topic
Arrange the inputs, invoke behavior, and assert the contract. Keep tests independent of execution order and wall-clock time. @BeforeEach sets up per-test state; shared mutable fixtures can make one test accidentally prepare another.
Parameterized tests run the same contract over a small meaningful input matrix. Include normal values, boundaries, and invalid inputs. A high coverage percentage does not prove assertions would catch a defect; introduce a deliberate bug locally to check test sensitivity.
EXAMPLE · JAVA
PagePolicyTest.java
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.*;
class PagePolicyTest {
@ParameterizedTest @ValueSource(ints = {1, 20, 100})
void acceptsBoundedSizes(int size) {
assertEquals(size, PagePolicy.checkedSize(size));
}
@ParameterizedTest @ValueSource(ints = {-1, 0, 101})
void rejectsInvalidSizes(int size) {
assertThrows(IllegalArgumentException.class, () -> PagePolicy.checkedSize(size));
}
}What to expect
Place beside the PagePolicy class from the pagination lesson with the Boot test dependencies. Six cases verify both acceptance and rejection boundaries.
YOUR TURN
Put it into practice
- 01Build a parameterized matrix for title validation.
- 02Introduce an off-by-one defect in maximum length and confirm a case fails.
- 03Verify: Tests run independently and fail for a known incorrect implementation.
Pass a quiz or complete a lab to check today’s streak. Each lesson counts once per day, including when you review it later.
UNDER THE HOOD
Build the mental model
A test should expose a specific defect through a precise observable assertion.
- 01Arrange the inputs, invoke behavior, and assert the contract. Keep tests independent of execution order and wall-clock time. @BeforeEach sets up per-test state; shared mutable fixtures can make one test accidentally prepare another.
- 02Parameterized tests run the same contract over a small meaningful input matrix. Include normal values, boundaries, and invalid inputs. A high coverage percentage does not prove assertions would catch a defect; introduce a deliberate bug locally to check test sensitivity.
- 03Trace the example: Place beside the PagePolicy class from the pagination lesson with the Boot test dependencies. Six cases verify both acceptance and rejection boundaries.
A mistake worth avoiding
Tests pass individually but fail when run together.
DEBUGGING ROOM
Something broke. Where do you look?
Tests pass individually but fail when run together.
Before revealing the diagnosis, write down your first investigation step.
CHECK YOUR UNDERSTANDING
Does line coverage alone prove a test would detect incorrect results?
BUILD IT YOURSELF
Build a parameterized matrix for title validation.
- 1.Build a parameterized matrix for title validation.
- 2.Introduce an off-by-one defect in maximum length and confirm a case fails.
- 3.Reproduce this failure, then repair it: Tests pass individually but fail when run together.
Acceptance checklist
Lab completion is your self-report. Knowledge checks do not certify project quality.
RETRIEVE IT FROM MEMORY
Does line coverage alone prove a test would detect incorrect results?
Revisit this lesson in three days after a successful check or lab.
Ready for the next step?
Tests run independently and fail for a known incorrect implementation.
Reading is separate from passing a knowledge check or completing a lab.