Mocking vs. Spying in mocking frameworks
Asked Answered
G

8

188

In mocking frameworks, you can mock an object or spy on it. What's the difference between the two and when would/should I use one over the other?

Looking at Mockito, for example, I see similar things being done using spies and mocks, but I am unsure as to the distinction between the two.

Giltzow answered 10/10, 2012 at 20:14 Comment(3)
martinfowler.com/bliki/TestDouble.htmlEconomist
Possible duplicate of https://mcmap.net/q/134569/-mockito-spy-vs-mock-duplicateNeurocoele
@Neurocoele This question is older than that one.Storyteller
T
222

Mock object replace mocked class entirely, returning recorded or default values. You can create mock out of "thin air". This is what is mostly used during unit testing.

When spying, you take an existing object and "replace" only some methods. This is useful when you have a huge class and only want to mock certain methods (partial mocking). Let me quote Mockito documentation:

You can create spies of real objects. When you use the spy then the real methods are called (unless a method was stubbed).

Real spies should be used carefully and occasionally, for example when dealing with legacy code.

When in doubt, use mocks.

Tectrix answered 10/10, 2012 at 20:22 Comment(6)
Thank you! That makes it much clearer. So mocks never delegate to the actual object being mocked ever, but spies do.Giltzow
Mocks don't have an "actual object" - the mock is created ab initio.Wondrous
Any explanation for why Mockito warns against using spies all the time? I see that they say to favor mocks, but I'm not clear on the reason why.Denton
I'm not sure, but maybe because they're "Mockito" and not "Spyito" :DBubonocele
My guess is they prefer mocks over spies because you want to restrict the code under test as much as possible when unit testing. By using a spy, you're allowing some of the real implementation code to run, allowing the code of that dependent class to be included in your test.Ahmadahmar
That is not really aligned with Meszaros' formal terminology. A spy is specialized stub (it returns test-specific values) but remembers what was done to it and allows the test to ask about it. Nothing is mentioned about partial mocking.... Mock is a specialized spy by adding concept of "expectations"Forfeit
F
33

I'll try to explain using an example here:

// Difference between mocking, stubbing and spying
@Test
public void differenceBetweenMockingSpyingAndStubbing() {
    List list = new ArrayList();
    list.add("abc");
    assertEquals(1, list.size());

    List mockedList = spy(list);
    when(mockedList.size()).thenReturn(10);
    assertEquals(10, mockedList.size());
}

Here, we had initial real object list, in which we added one element and expected size to be one.

We spy real object meaning that we can instruct which method to be stubbed. So we declared that we stubbed method - size() on spy object which will return 10, no matter what is actual size.

In a nutshell, you will spy real object and stub some of the methods.

Fennie answered 19/10, 2015 at 19:14 Comment(0)
P
20

Mockito warns that partial mocking isn't a good practice and you should revise your Object Oriented architecture. Spy (or partial mocking) is recommended to test legacy code.

Permittivity answered 17/1, 2014 at 19:4 Comment(0)
C
20

Based on Mocks Aren't Stubs by Martin Fowler:

Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.

Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).

Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.

Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.

Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.

Casserole answered 16/12, 2019 at 21:36 Comment(0)
D
8

In Mockito if you assign any object to instance variable of Mock Object then does not affect on Mock Object.

But in case of Spy, if you assign any object to instance variable of Spy Object then does affect on Spy Object because of Spy act like real-time object modification.

For a reference example are

@RunWith(MockitoJUnitRunner.class)
public class MockSpyExampleTest {

    @Mock
    private List<String> mockList;

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

    @Test
    public void testMockList() {
        //by default, calling the methods of mock object will do nothing
        mockList.add("test");
        assertNull(mockList.get(0));
    }

    @Test
    public void testSpyList() {
        //spy object will call the real method when not stub
        spyList.add("test");
        assertEquals("test", spyList.get(0));
    }
}
Duralumin answered 3/9, 2019 at 11:27 Comment(0)
G
3

Reference: http://javapointers.com/tutorial/difference-between-spy-and-mock-in-mockito/

When using mock objects, the default behavior of the method when not stub is do nothing. Simple means, if its a void method, then it will do nothing when you call the method or if its a method with a return then it may return null, empty or the default value.

While in spy objects, of course, since it is a real method, when you are not stubbing the method, then it will call the real method behavior. If you want to change and mock the method, then you need to stub it.

Galvan answered 21/10, 2015 at 7:24 Comment(0)
U
1

Spies have two definitions. One, is where the real method is called, another where, no functionality is called and only null or null equivalent values are returned, but methods were called, and they're state was recorded, commonly like, method x was called y times.

Untune answered 19/11, 2014 at 19:55 Comment(0)
A
0

If we want to avoid calling external services and just want to test the logic inside the method then use mock.

If we want to call the external services and use the real dependency i.e to run the program as it is and just stub specific methods then use spy

Advent answered 2/7, 2022 at 18:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.