0
0
JunitComparisonBeginner · 4 min read

Mock vs Spy in Mockito in JUnit: Key Differences and Usage

In Mockito for JUnit, a mock creates a fake object with no real behavior unless specified, while a spy wraps a real object allowing you to call real methods and selectively stub others. Use mock to isolate dependencies completely and spy when you want to partially mock an existing object.
⚖️

Quick Comparison

Here is a quick side-by-side comparison of mock and spy in Mockito:

FactorMockSpy
Object TypeFake object with no real behaviorWraps a real object
Method CallsAll methods return default or stubbed valuesCalls real methods unless stubbed
Use CaseIsolate dependencies fullyPartial mocking of real objects
State ChangesNo real state changes unless stubbedReal state changes happen
CreationMockito.mock(Class.class)Mockito.spy(realObject)
PerformanceUsually faster, no real logic executedSlower, real methods executed
⚖️

Key Differences

Mock creates a completely fake version of a class or interface. It does not execute any real code unless you explicitly tell it what to do using stubbing. This is useful when you want to isolate the unit under test from its dependencies and control all interactions.

On the other hand, spy wraps an existing real object. By default, it calls the real methods of that object. You can selectively override some methods with stubbing. This allows you to test parts of the real object while controlling or verifying others.

Because spy calls real methods, it can cause side effects or state changes in the wrapped object, which mock avoids. Therefore, spy is best when you want to test real behavior but still monitor or override some parts.

⚖️

Code Comparison

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

import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;

class MockExampleTest {

    @Test
    void testMockList() {
        List<String> mockedList = mock(ArrayList.class);

        // Stubbing size method
        when(mockedList.size()).thenReturn(5);

        // Calling size returns stubbed value
        assertEquals(5, mockedList.size());

        // Calling add does nothing real
        mockedList.add("one");
        assertEquals(5, mockedList.size()); // still 5, no real add

        // Verify add was called
        verify(mockedList).add("one");
    }
}
Output
Test passes with assertions confirming stubbed size and method call verification.
↔️

Spy Equivalent

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

import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;

class SpyExampleTest {

    @Test
    void testSpyList() {
        List<String> realList = new ArrayList<>();
        List<String> spyList = spy(realList);

        // By default, calls real method
        spyList.add("one");
        assertEquals(1, spyList.size()); // real size is 1

        // Stub size method
        when(spyList.size()).thenReturn(5);
        assertEquals(5, spyList.size()); // stubbed value

        // Verify add was called
        verify(spyList).add("one");
    }
}
Output
Test passes with real add method called and size stubbed to 5.
🎯

When to Use Which

Choose mock when: You want to isolate the unit under test completely from its dependencies and control all interactions without executing any real code. This is ideal for testing behavior without side effects.

Choose spy when: You want to test a real object but override or verify some methods selectively. This is useful for partial mocking when you want to keep real behavior but control or observe specific parts.

In summary, use mock for full fake objects and spy for partial real objects.

Key Takeaways

Use mock to create fully fake objects with no real method execution.
Use spy to wrap real objects and call real methods unless stubbed.
Mocks isolate dependencies completely; spies allow partial mocking with real behavior.
Mocks avoid side effects; spies can cause real state changes.
Choose mocks for unit isolation and spies for partial behavior control.