Discover how choosing the right test double can save hours of debugging and frustration!
Why different doubles serve different purposes in JUnit - The Real Reasons
Imagine testing a complex app where you must check how parts work together. You try to test one part but it needs other parts to work first. You manually create fake versions of these parts by writing lots of code for each test.
This manual way is slow and confusing. You write many fake parts that don't behave quite right. Tests break often because your fakes don't match real parts. It's hard to know if a test fails because of your code or your fake parts.
Using different test doubles like mocks, stubs, and spies helps you create just the right fake for each need. Each double has a clear role, making tests simpler, faster, and more reliable. You focus on testing one thing at a time without extra hassle.
FakeDatabase db = new FakeDatabase(); // lots of code to simulate behavior TestService service = new TestService(db); service.runTest();
Database db = mock(Database.class); when(db.getData()).thenReturn("test data"); TestService service = new TestService(db); service.runTest();
It enables writing clear, focused tests that quickly find real problems without getting lost in fake code details.
When testing a payment system, you use a stub to simulate payment approval, a mock to check if the notification was sent, and a spy to verify logging happened—all in one test.
Manual fakes are slow and error-prone.
Different doubles serve clear, distinct roles.
Using the right double makes tests simpler and more reliable.
Practice
Solution
Step 1: Understand the role of a stub
A stub provides fixed data or responses to the code being tested but does not check if methods were called.Step 2: Differentiate from mocks and spies
Mocks verify interactions, spies do both spying and stubbing, and fakes are simplified implementations. Only stubs focus on providing data without verification.Final Answer:
Stub -> Option AQuick Check:
Stub = provides data only [OK]
- Confusing mocks with stubs
- Thinking spies only provide data
- Mixing fakes with stubs
Solution
Step 1: Recall Mockito syntax for mocks
Mockito.mock(Class.class) creates a mock object for the given class.Step 2: Identify incorrect options
MyClass mock = new MyClass(); creates a real object, not a mock. MyClass mock = spy(new MyClass()); creates a spy, not a mock. MyClass mock = new FakeMyClass(); uses a fake class, not a mock.Final Answer:
MyClass mock = Mockito.mock(MyClass.class); -> Option CQuick Check:
Mockito.mock() creates mocks [OK]
- Using new keyword instead of Mockito.mock
- Confusing spy() with mock()
- Assuming fake classes are mocks
List<String> list = Mockito.spy(new ArrayList<>());
list.add("one");
Mockito.verify(list).add("one");
System.out.println(list.size());What will be printed?
Solution
Step 1: Understand spy behavior
A spy wraps a real object and records interactions but calls real methods unless stubbed.Step 2: Analyze the code execution
Adding "one" to the spy list calls the real add method, so the list size becomes 1. The verify confirms the add call happened.Final Answer:
1 -> Option DQuick Check:
Spy calls real methods and records calls [OK]
- Thinking spy does not call real methods
- Assuming size remains 0 after add
- Expecting null or exception output
MyService service = Mockito.mock(MyService.class); service.process(); Mockito.verify(service.process());
Solution
Step 1: Understand Mockito verify syntax
Mockito.verify() expects the mock object as argument, then the method call without parentheses inside verify.Step 2: Identify the mistake in code
The code calls verify(service.process()), which calls process() immediately and passes its result. Correct is verify(service).process().Final Answer:
verify() should receive a method call without parentheses -> Option BQuick Check:
Use verify(mock).method() syntax [OK]
- Calling method inside verify() parentheses
- Calling verify before method execution
- Confusing mock initialization with verification
Solution
Step 1: Understand requirements for the test double
You want to verify the method call (like a mock) and also provide a fixed response (like a stub).Step 2: Identify the double that combines both features
A mock verifies interactions and can return fixed responses when configured with when(mock.method(params)).thenReturn(success).Final Answer:
Mock -> Option AQuick Check:
Mock = verify calls + stub data [OK]
- Using stub which can't verify calls
- Using spy which executes real methods unless stubbed
- Confusing fake with mock
Ready to prove it?
Pass the test and this pattern moves unknown
