单元测试–Mockito之spy
1. apy
* mockito中实现部分mock的方式,及使用Mockito mock当前类【同一类】中的部分方法
* 部分mock是说一个类的方法有些是实际调用,有些是使用mockito的stubbing(桩实现)
- spy和mock的相同点和区别:
- 1.得到的对象同样可以进行“监管”,即验证和打桩。
- 2.如果不对spy对象的methodA打桩,那么调用spy对象的methodA时,会调用真实方法。
- 3.如果不对mock对象的methodA打桩,将doNothing,且返回默认值(null,0,false)。
2. @SpyBean 和 @MockBean 区别,以及@Spy 和 @Mock的区别
- 默认行为的不同
- 对于未进行mock的方法,@Spy和@SpyBean生成的对象默认会调用真实的方法,有返回值的返回真实的返回值
- 而@Mock和@MockBean生成的对象对于未进行mock的方法,默认不执行,有返回值的,默认返回null
- mock的使用方式不同
@Mock和@MockBean生成的对象的使用 when/then: 包括when(…).thenReturn(…)/when(…).thenAnswer(…)方式,@spy对象这样使用会直接调用该方法,但有返回值的返回为then后的返回值
//when().thenReturn第一次调用methodA()会真是调用,但返回值为thenReturn的返回值
when(testSpy.methodA()).thenReturn(0);
对@Spy和@SpyBean生成的对象的mock时,要先执行do等方法,调用时才不会调用真实的方法
do/when:包括doThrow(…).when(…)/doReturn(…).when(…)/doAnswer(…).when(…)
- @spy和@mock生成的对象不受spring管理
- @spy调用真实方法时,其它bean是无法注入的,要使用注入,要使用@SpyBean
- @SpyBean和@MockBean生成的对象受spring管理,相当于自动替换对应类型bean的注入,比如@Autowired等注入
3. 代码实例
public class TestSpy {
public int methodA(){
//根据某成员变量的值去计算得出一个value,这个过程包含了复杂的逻辑和层层方法嵌套调用
int a = 100;
System.out.println("methodA");
return a;
}
public void methodB(){
int key = methodA();
switch(key){
case 0:
System.out.println("case 0");
//do something
break;
case 1:
System.out.println("case 1");
//do something
break;
case 2:
System.out.println("case 2");
//do something
break;
}
}
}
Test
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.junit4.SpringRunner;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestSpyTest {
@SpyBean
private TestSpy testSpy;
//此用例中使用testSpy的原因是我要测试的是TestSpy 的methodB方法,所以需要
//调用真实对象的methodB,methodB的输入来自methodA的返回值。但是methodA的计算十分复杂,
//那么想要methodA返回你想要的值就不那么容易,别人看起来也不直观,不确定methodA否是真的
//返回0,1,2。那么就可以对methodA打桩,对真实对象打桩,就要用到testSpy.
@Test
public void testMethodB(){
//TestSpy t = new TestSpy();
//TestSpy spyT = Mockito.spy(t);
/*when().thenReturn第一次调用methodA()会真是调用,但返回值为thenReturn的返回值
第一次,第二次,第三次调用methodA时,分别返回0,1,2*/
when(testSpy.methodA()).thenReturn(0,1,2);
/*doReturn().when() 和不会真是调用methodA()方法
第一次,第二次,第三次调用methodA时,分别返回0,1,2*/
Mockito.doReturn(0,1,2).when(testSpy).methodA();
for(int i=0; i<=2; i++){
testSpy.methodB();
}
//assert && verify
}
}
输出结果
使用when(testSpy.methodA()).thenReturn(0,1,2);打桩
使用 Mockito.doReturn(0,1,2).when(testSpy).methodA();打桩