0
0
JUnittesting~5 mins

@Spy for partial mocking in JUnit

Choose your learning style9 modes available
Introduction

@Spy lets you test real objects but still control or check some parts of their behavior. It helps when you want to test most of the real code but replace or watch a few methods.

You want to test a real object but mock only some methods.
You want to verify if certain methods were called on a real object.
You want to keep the original behavior but override specific parts.
You want to avoid writing a full mock for a complex class.
You want to combine real logic with controlled test behavior.
Syntax
JUnit
@Spy
private ClassName objectName;

Use @Spy on a field to create a partial mock of that object.

You can use Mockito.when() to override specific methods.

Examples
This creates a spy on a real ArrayList object.
JUnit
@Spy
private List<String> spyList = new ArrayList<>();
This creates a spy on MyService. You can override some methods if needed.
JUnit
@Spy
private MyService service;
This overrides the size() method to return 100, even though spyList is a real list.
JUnit
Mockito.when(spyList.size()).thenReturn(100);
Sample Program

This test creates a spy on a real ArrayList. It adds two items, then overrides the size() method to return 100. The get(0) method still returns the real value. The test also verifies that add("one") was called.

JUnit
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(MockitoExtension.class)
public class SpyExampleTest {

    @Spy
    private List<String> spyList = new ArrayList<>();

    @Test
    public void testSpyPartialMocking() {
        spyList.add("one");
        spyList.add("two");

        // Override size method
        when(spyList.size()).thenReturn(100);

        // Real methods work
        assertEquals("one", spyList.get(0));

        // Overridden method returns mocked value
        assertEquals(100, spyList.size());

        // Verify method call
        verify(spyList).add("one");
    }
}
OutputSuccess
Important Notes

Use @Spy when you want to keep most real behavior but control some parts.

Remember to initialize spies properly, for example with MockitoExtension in JUnit 5.

Be careful: overriding too many methods can make tests confusing.

Summary

@Spy creates a partial mock of a real object.

You can override or verify specific methods while keeping others real.

It helps test complex objects without full mocking.