Loading published curriculum…

17 · Tests and migrations / LESSON 85 OF 102

Unit tests and test doubles

Test business behavior without starting infrastructure.

Before this lesson: Rate limits, reset tokens, and security review

Understand the topic

Use the test dependencies generated by Initializr. Construct the service directly and assert observable outputs or failures. Test normal, boundary, and invalid inputs rather than mirroring every implementation line.

Use a test double when a collaborator is expensive or nondeterministic. A unit test does not prove HTTP, security filters, JSON serialization, or JPA mappings; wider tests cover those boundaries.

EXAMPLE · JAVA

src/test/java/com/example/tasks/TitleServiceTest.java

package com.example.tasks;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class TitleServiceTest {
    private final TitleService service = new TitleService();
    @Test void trimsWhitespace() {
        assertEquals("Java", service.normalize("  Java  "));
    }
    @Test void rejectsBlank() {
        assertThrows(IllegalArgumentException.class,
            () -> service.normalize("   "));
    }
}

What to expect

./mvnw test runs these tests without starting Spring; Windows uses .\mvnw.cmd test.

YOUR TURN

Put it into practice

  1. 01Add a null-input test.
  2. 02Break normalize, observe failure, then restore it.
  3. 03List which behavior requires integration testing.

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 useful test describes behavior that should remain true even if the implementation changes.

  1. 01Arrange a small input, act once, and assert an observable result. Avoid incidental details such as a private helper being called in a certain order.
  2. 02Use boundary examples that would reveal realistic defects: null, whitespace, maximum length, and a normal value.
  3. 03A test double belongs at a real dependency boundary. Mocking every value object makes tests fragile and hides integration assumptions.

A mistake worth avoiding

A green test with no meaningful assertion provides little evidence.

DEBUGGING ROOM

Something broke. Where do you look?

Refactoring a private method breaks dozens of tests without changing behavior.

Before revealing the diagnosis, write down your first investigation step.

CHECK YOUR UNDERSTANDING

Which is the strongest assertion for title normalization?

Choose one answer

BUILD IT YOURSELF

Create a meaningful test matrix

  1. 1.Cover normal, null, blank, and boundary inputs.
  2. 2.Introduce a deliberate defect and confirm a test catches it.
  3. 3.Keep tests independent of time, network, and execution order.

Acceptance checklist

Lab completion is your self-report. Knowledge checks do not certify project quality.

RETRIEVE IT FROM MEMORY

What defect would this test catch?

Revisit this lesson in three days after a successful check or lab.

Ready for the next step?

Write a test that catches a real regression.

Reading is separate from passing a knowledge check or completing a lab.

Go deeper · official references