0
0
JUnittesting~5 mins

Spy objects in JUnit

Choose your learning style9 modes available
Introduction

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.

You want to verify that a method was called on an object during a test.
You need to check the arguments passed to a method without mocking the whole object.
You want to keep the original behavior of an object but still track its interactions.
You are testing a class that depends on another class and want to observe how it uses that class.
You want to debug or understand the flow of method calls in your code during testing.
Syntax
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.

Examples
This example spies on a real list. It adds an item and verifies the add method was called with "apple".
JUnit
List<String> list = new ArrayList<>();
List<String> spyList = Mockito.spy(list);

spyList.add("apple");
Mockito.verify(spyList).add("apple");
Here, the spy is used to override the getData() method to return a mocked result, while still tracking calls.
JUnit
MyService service = new MyService();
MyService spyService = Mockito.spy(service);

Mockito.doReturn("mocked result").when(spyService).getData();

String result = spyService.getData();
Mockito.verify(spyService).getData();
Sample Program

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.

JUnit
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);
    }
}
OutputSuccess
Important Notes

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.

Summary

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.