Test doubles help us test parts of a program by replacing real parts with simple stand-ins. This makes testing easier and faster.
0
0
Choosing the right test double in JUnit
Introduction
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.