单元测试框架Mockito中的mock和spy概念怎么理解?

1,416 阅读1分钟

mock和spy都是test double(测试替身)的其中一种,我们都可以对其进行stub,但是他们两个使用场景却截然不同。

我们先来看一段代码(测试方法都是可以通过的):

@ExtendWith(MockitoExtension.class)
public class MockSpyTest {

    @Mock
    private List<String> mockList;

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

    @Test
    public void testSpyList() {
        // 调用真实对象的add方法              
        spyList.add("abc");                // 1
        assertEquals(1, spyList.size());        
        // stub
        when(spyList.size()).thenReturn(10);
        // 校验size是否为
        assertEquals(10, spyList.size());
    }

    @Test
    public void testMockList() {
        // 调用mock对象的add方法
        mockList.add("abc");            // 2
        assertEquals(0, mockList.size());
        // stub
        when(mockList.size()).thenReturn(10);
        assertEquals(10, mockList.size());
    }

}
  1. 当我们调用spyList#add的时候,add的方法是被真实调用了,因此spyList的size是1
  2. 当我们调用mockList#add的时候,add的方法并没有被真实调用,因此spyList的size是0

无论是spy还是mock出的对象,stub的效果都是一致的,list集合size都是我们想要的10。


那什么时候应该用spy,什么时候应该用mock呢?

  • 不想调用真实的方法,只是想对其行为进行stub。例如发送邮件给客户,这种场景下我们并不想真的发送邮件给客户,这个时候应该使用mock。
  • 想调用真实的方法,并且执行一些代码逻辑,然后观测其行为,这个时候我们应该使用spy。例如邮件发送人为自己,然后对发送邮件之外的方法进行stub,观测我们程序的行为并进行verify。

Reference