What if you could watch your code's every move during tests without changing a thing?
Why Spy objects in JUnit? - Purpose & Use Cases
Imagine testing a calculator app by manually writing down every button press and checking the result yourself each time.
You want to see if the calculator remembers previous inputs correctly, but you have no easy way to watch what happens inside the app.
Manually tracking internal method calls or data changes is slow and error-prone.
You might miss important details or make mistakes when guessing what happened inside the code.
This makes tests unreliable and debugging frustrating.
Spy objects let you watch real objects during tests.
You can see which methods were called, with what data, without changing the original behavior.
This helps you verify internal actions easily and confidently.
Calculator calc = new Calculator(); calc.add(5); // Manually check if add was called and result is correct
Calculator calc = spy(new Calculator()); calc.add(5); verify(calc).add(5);
Spy objects enable precise checking of internal method calls while keeping real behavior intact.
Testing a shopping cart where you want to confirm that adding an item calls the inventory check method exactly once.
Manual tracking of internal calls is slow and unreliable.
Spy objects watch real objects without changing them.
This makes tests clearer, faster, and more trustworthy.
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
