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.