在测试过程中,有个类的部分方法可能需要实际调用,而某些方法则是被mock的,也就是部分mock的场景。在Mockito中,可以使用Spy来实现。首先来看一个最简单的案例
public class SpyDemo {
@Spy
List<String> spy= new ArrayList<String>(); ;
@BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void TestSimpleSpy() {
spy.add("one");
spy.add("two");
when(spy.size()).thenReturn(100);
assertThat(spy.size()).isEqualTo(100);
assertThat(spy.get(0)).isEqualTo("one");
}
对于Spy来说,没有被打桩的调用默认都会执行真实的方法,如果是打过桩的则返回桩实现。在上述案例中,spy.size()通过桩实现返回了值100,而spy.get(0)则返回了实际值。
@Test
public void TestSayHello() {
Demo demo=spy(new Demo();
when(demo.hello()).thenReturn("Ni hao r u");
assertThat(demo.hello()).isEqualTo("Ni hao r u");
}
class Demo {
public String hello() {
System.out.println("hello");
return "hello";
}
}
通过执行这个用例,会发现虽然用例执行通过了,也就是demo.hello()的调用结果为返回"Ni hao r u"。但是,Mockito除了按照测试桩返回预期值之外,还调用了真实的hello()方法,也就是在终端打印出了“hello”。 换一种写法,使用doReturn.when的方式,
@Test
public void TestSayHello2() {
doReturn("Ni hao r u").when(demo).hello();
assertThat(demo.hello()).isEqualTo("Ni hao r u");
reset(demo);
assertThat(demo.hello()).isEqualTo("hello");
}
在这个情况下,真实的hello方法就不会被调用了。 When(obj.do()) 还是 when(obj).do()的写法,在之前介绍void方法测试时其实也有涉及到。由于when(obj.do())的类型检查,void方法采用这种写法,会直接在编译器的语法检查中失败。
在测试过程中,如果在设置了测试桩之后,还想调用真实方法来执行,则可以使用Mockito.reset来重置spy。如上一个用例中,在第二次调用demo.hello()方法前调用了reset方法重置demo,因此,这次方法调用的返回值就是”hello”。
1)When(obj.do()).thenXXX方法是类型安全的,一般情况下推荐使用。 2)doXX().when(obj).do()方法可以避免在spy时默认执行真实方法 3)可以通过reset方式去掉测试桩