Mockito Spy 用法

概述

本文将详细阐述如何充分利用Mockito中的Spy,我们将讨论@Spy注解,如何给spy打桩,以及最后我们介绍了Mock和SPy之间的区别。

想了解更多的Mockito用法,参看这一系列,Mockito

简单的使用Spy例子

首先我们通过一个例子来学习下如何使用spy。 我们只需要简单的对一个真实的对象调用API,Mokito.spy()。我们便可以在把持该对象的所有正常方法调用的同时,还能像mock对象一样来对他配置一些行为。 好吧,让我们来快速看一个spy一个ArrayList的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void whenSpyingOnList_thenCorrect() {
List<String> list = new ArrayList<String>();
List<String> spyList = Mockito.spy(list);
spyList.add("one");
spyList.add("two");
Mockito.verify(spyList).add("one");
Mockito.verify(spyList).add("two");
assertEquals(2, spyList.size());
}

请注意,list对象的真实的add方法被调用,同时spyList的size变为了2

@Spy注解

接着,我们看一下如何使用@Spy注解,下面的例子中我们使用@Spy注解替换了spy()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Spy
List<String> spyList = new ArrayList<String>();
@Test
public void whenUsingTheSpyAnnotation_thenObjectIsSpied() {
spyList.add("one");
spyList.add("two");
Mockito.verify(spyList).add("one");
Mockito.verify(spyList).add("two");
assertEquals(2, spyList.size());
}

在使用Mockito的注解(比如说@Mock,@Spy)等时,我们需要做如下配置:

  • 调用MockitoAnnotations.initMocks(this)方法对注解对象进行初始化
  • 使用内置的runner @RunWith(MockitoJUnitRunner.class)

为spy对象打桩

我们可以像使用mock对象时的语法一样,配置或者说重新改写spy对象的方法, 下面的例子我们使用了doReturn()来重写了size()方法:

1
2
3
4
5
6
7
8
9
10
@Test
public void whenStubASpy_thenStubbed() {
List<String> list = new ArrayList<String>();
List<String> spyList = Mockito.spy(list);
assertEquals(0, spyList.size());
Mockito.doReturn(100).when(spyList).size();
assertEquals(100, spyList.size());
}

Mock vs. Spy

最后,我们来讨论一下在Mokita中Mock和Spy有什么区别。 当Mockito创造一个mock对象时,它是从类的类型中创建,而不是从类的实例中创建。也就是说mock对象是一个简单的只带有骨架的空壳的对象实例,同时我们可以跟踪它的所有交互方法。 不同的是,spy对象是对一个对象实例进行的封装,它仍然能够像正常对象实例一样有这正常的行为,唯一不同的是这些行为交互是可以跟踪和配置的。下面我们穿件一个mock的list例子:

1
2
3
4
5
6
7
8
9
@Test
public void whenCreateMock_thenCreated() {
List mockedList = Mockito.mock(ArrayList.class);
mockedList.add("one");
Mockito.verify(mockedList).add("one");
assertEquals(0, mockedList.size());
}

可见,对mock的list增加一个元素并没有实际的真假任何东西,它仅仅是调用了该方法,没有任何的其他影响。 而spy对象则不同,它会真是的在该对象中增加一个元素:

1
2
3
4
5
6
7
8
9
@Test
public void whenCreateSpy_thenCreate() {
List spyList = Mockito.spy(new ArrayList());
spyList.add("one");
Mockito.verify(spyList).add("one");
assertEquals(1, spyList.size());
}

总结

本文通过几个简单例子讨论了如何充分利用Mockito中的spy方法。我们学习了如何创建一个spy对象,如何使用@Spy注解,最后比较了Spy与Mock的区别。例子 代码实现可以参见github。想了解更多的Mockito用法,参看这一系列,Mockito

请我喝杯咖啡吧!