Spy objects help you watch how real objects behave during tests. They let you check what methods were called and with what data, without changing the real object's behavior.
Spy objects in JUnit
MyClass realObject = new MyClass();
MyClass spyObject = Mockito.spy(realObject);
// Use spyObject in your test
Mockito.verify(spyObject).methodName(expectedArgument);Spy wraps a real object, so the original methods run unless stubbed.
Use Mockito.verify() to check method calls on the spy.
List<String> list = new ArrayList<>(); List<String> spyList = Mockito.spy(list); spyList.add("apple"); Mockito.verify(spyList).add("apple");
getData() method to return a mocked result, while still tracking calls.MyService service = new MyService();
MyService spyService = Mockito.spy(service);
Mockito.doReturn("mocked result").when(spyService).getData();
String result = spyService.getData();
Mockito.verify(spyService).getData();This test creates a spy of a real list. It adds two fruits, then verifies the add method was called with each fruit. It also checks the list size is 2, showing the real methods ran.
import static org.mockito.Mockito.*; import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; public class SpyTest { @Test public void testSpyObject() { List<String> realList = new ArrayList<>(); List<String> spyList = spy(realList); spyList.add("banana"); spyList.add("orange"); verify(spyList).add("banana"); verify(spyList).add("orange"); assert(spyList.size() == 2); } }
Spies call real methods by default, so be careful with side effects.
You can stub spy methods to change behavior using doReturn() or when().
Use spies when you want to partially mock an object but keep most behavior real.
Spy objects let you watch real objects during tests without changing their behavior by default.
They help verify method calls and arguments while keeping original logic intact.
Use spies to combine real behavior with verification in your unit tests.
Practice
spy object in JUnit testing?Solution
Step 1: Understand spy object behavior
A spy wraps a real object, allowing it to behave normally while tracking interactions.Step 2: Identify spy's main use
Spies let you verify if certain methods were called without changing the real behavior.Final Answer:
To observe real object behavior and verify method calls -> Option CQuick Check:
Spy = observe real + verify calls [OK]
- Confusing spy with mock that replaces behavior
- Thinking spy speeds up tests by skipping calls
- Believing spy generates test data
Solution
Step 1: Recall Mockito spy syntax
Mockito creates a spy by wrapping a real instance:Mockito.spy(realObject).Step 2: Match options to syntax
MyClass spy = Mockito.spy(new MyClass()); correctly usesMockito.spy(new MyClass())to create a spy.Final Answer:
MyClass spy = Mockito.spy(new MyClass()); -> Option AQuick Check:
Spy creation = Mockito.spy(real instance) [OK]
- Using Mockito.mock() instead of spy()
- Trying to spy without a real instance
- Confusing verify() with spy()
List<String> list = new ArrayList<>();
List<String> spyList = Mockito.spy(list);
spyList.add("apple");
spyList.add("banana");
Mockito.verify(spyList).add("apple");
System.out.println(spyList.size());Solution
Step 1: Understand spy behavior on add()
Spy calls real methods, soadd("apple")andadd("banana")add elements to the list.Step 2: Verify method call and size
Verification confirmsadd("apple")was called. The list now contains two elements, sosize()returns 2.Final Answer:
2 -> Option DQuick Check:
Spy calls real methods, size = 2 [OK]
- Assuming spy does not call real methods
- Expecting size to be 0 after add calls
- Confusing verify with changing behavior
List<String> list = new ArrayList<>();
List<String> spyList = Mockito.spy(list);
Mockito.when(spyList.size()).thenReturn(5);
spyList.add("orange");
System.out.println(spyList.size());Solution
Step 1: Recognize stubbing on spy
Stubbing spy methods withMockito.when()can cause real method calls and errors.Step 2: Correct stubbing approach
UsedoReturn(5).when(spyList).size()to stub spy methods safely.Final Answer:
Cannot stub spy methods with Mockito.when() directly -> Option BQuick Check:
Spy stubbing = use doReturn() not when() [OK]
- Using Mockito.when() on spy causing real calls
- Confusing spy creation with mock creation
- Thinking interfaces can't be spied
save() method. You want to keep the real repository behavior but verify save() was called exactly once. Which is the best approach using spy objects?Solution
Step 1: Understand spy use case
Spy lets real methods run while tracking calls, perfect for verifyingsave()without changing behavior.Step 2: Apply spy to repository and verify
Create spy of repository, call service method, then verifysave()was called once.Final Answer:
Create a spy of the repository, call the service method, then verifysave()was called once -> Option AQuick Check:
Spy = real behavior + verify calls [OK]
- Mocking instead of spying loses real behavior
- Checking database manually is slow and unreliable
- Verifying save was never called contradicts test goal
Ready to prove it?
Pass the test and this pattern moves unknown
