0
0
JUnittesting~5 mins

Choosing the right test double in JUnit

Choose your learning style9 modes available
Introduction

Test doubles help us test parts of a program by replacing real parts with simple stand-ins. This makes testing easier and faster.

When a real part is slow or hard to use during testing.
When a real part is not ready yet but you want to test other parts.
When you want to control the behavior of a part to test specific cases.
When a real part causes side effects like sending emails or changing a database.
When you want to check if a part was used correctly during the test.
Syntax
JUnit
public class TestClass {
    @Test
    public void testMethod() {
        Dependency dep = mock(Dependency.class); // create a test double
        when(dep.someMethod()).thenReturn(someValue); // define behavior
        // use dep in the class under test
    }
}

Use mock() to create a test double that imitates a real object.

Use when(...).thenReturn(...) to set what the test double should do when called.

Examples
This creates a mock of Dependency and makes getData() return "TestData".
JUnit
Dependency dep = mock(Dependency.class);
when(dep.getData()).thenReturn("TestData");
This creates a spy that wraps a real Dependency object but overrides getData() to return "SpyData".
JUnit
Dependency dep = spy(new Dependency());
doReturn("SpyData").when(dep).getData();
This checks if someMethod() was called on the mock during the test.
JUnit
Dependency dep = mock(Dependency.class);
verify(dep).someMethod();
Sample Program

This test uses a mock as a test double for Dependency. It sets getData() to return "hello". The Service class uses this mock, and the test checks if the output is "HELLO" and if getData() was called.

JUnit
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class Service {
    private final Dependency dep;
    public Service(Dependency dep) {
        this.dep = dep;
    }
    public String process() {
        return dep.getData().toUpperCase();
    }
}

interface Dependency {
    String getData();
}

public class ServiceTest {
    @Test
    public void testProcess() {
        Dependency dep = mock(Dependency.class);
        when(dep.getData()).thenReturn("hello");
        Service service = new Service(dep);
        String result = service.process();
        assertEquals("HELLO", result);
        verify(dep).getData();
    }
}
OutputSuccess
Important Notes

Mocks are good when you want to check interactions and control behavior.

Spies wrap real objects but let you override some behavior.

Choose the test double type based on what you want to test: behavior, state, or interaction.

Summary

Test doubles replace real parts to make testing easier and safer.

Use mocks to fake behavior and verify calls.

Pick the right test double type to match your test goal.