部分mock
在測試過程中,有個類的部分方法可能需要實際調(diào)用,而某些方法則是被mock的,也就是部分mock的場景。在Mockito中,可以使用Spy來實現(xiàn)。首先來看一個最簡單的案例
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來說,沒有被打樁的調(diào)用默認都會執(zhí)行真實的方法,如果是打過樁的則返回樁實現(xiàn)。在上述案例中,spy.size()通過樁實現(xiàn)返回了值100,而spy.get(0)則返回了實際值。
When(obj.do()) 還是 when(obj).do() ?
@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";
}
}
通過執(zhí)行這個用例,會發(fā)現(xiàn)雖然用例執(zhí)行通過了,也就是demo.hello()的調(diào)用結(jié)果為返回"Ni hao r u"。但是,Mockito除了按照測試樁返回預期值之外,還調(diào)用了真實的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方法就不會被調(diào)用了。
When(obj.do()) 還是 when(obj).do()的寫法,在介紹之前void方法測試時其實也有涉及到。由于when(obj.do())的類型檢查,void方法采用這種寫法,會直接在編譯器的語法檢查中失敗。
Mockito.reset
在測試過程中,如果在設(shè)置了測試樁之后,還想調(diào)用真實方法來執(zhí)行,則可以使用Mockito.reset來重置spy。如上一個用例中,在第二次調(diào)用demo.hello()方法前調(diào)用了reset方法重置demo,因此,這次方法調(diào)用的返回值就是”hello”。
總結(jié)一下,
1)When(obj.do()).thenXXX方法是類型安全的
2)doXX().when(obj).do()方法可以避免在spy時默認執(zhí)行真實方法
3)可以通過reset方式去掉測試樁