1 Mockito简介
1.1 Mockito是什么
Mockito是一个简单的流行的Mock框架。它允许你创建和配置mock对象。使用Mockito可以明显的简化对外部依赖的测试类的开发。一般使用 Mockito 需要执行下面三步:
模拟并替换测试代码中外部依赖;
执行测试代码;
验证测试代码是否被正确的执行。
1.2 Mock是什么
Mock测试就是在测试过程中,对某些不容易构造或者不容易获取的对象,用一个虚拟的Mock对象来创建以便测试的测试方法。
Mock最大的功能是帮你把单元测试的耦合分解开,如果你的代码对另一个类或者接口有依赖,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为。
2 Mockito在Spring框架中的使用
2.1 依赖包
<dependency> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.21.0</version>
<scope>test</scope>
</dependency> |
Mockito在Spring可以通过配置文件和注解的方式使用
2.2 通过xml配置文件使用Mockito
Mockito创建方式有两种:mock,spy。mock为一个interface提供一个虚拟的实现,spy为object加一个动态代理,实现部分方法的虚拟化,但是需要赋予一个instance。
Mockito提供了factory的方法用来创建mock和spy。
假设构造系统中有serviceA,serviceB,serviceC,其中serviceA依赖serviceB依赖serviceC。serviceC是最基本的。现在需要对其中serviceA进行测试,但其serviceC需要依赖于外部环境,而这个环境需要复杂而且不稳定的数据库。这时需要mock或spy掉serviceC。
https://sq.163yun.com/blog/article/169561874192850944
第一步:在配置文件中注入mock:
<bean id="serviceC" class="org.mockito.Mockito"factory-method="mock">
<constructor-arg value="com.x.y.x.ServiceC"></constructor-arg>
</bean> |
或注入spy
<bean id="serviceCInst" class="serviceCInstance">
</bean><bean id="serviceC" class="org.mockito.Mockito" factory-method="spy">
<constructor-arg ref="serviceCInst"></constructor-arg>
</bean> |
spy需要获得一个实例。
第二步:
在测试用例中@Resource或@Autowired引入serviceC。
2.3 通过注解使用Mockito
以代码举例
@Componentpublic class OrderCreate {
@Resource
private OrderHelper orderHelper;
public void create() {
System.out.println(getAmt());
System.out.println(orderHelper.resolve());
}
public int getAmt() {
return 10;
}
} |
@Componentpublic class OrderHelper {
public String resolve() {
return "resolve order";
}
} |
测试类:
public class MockSpringTest {
@InjectMocks
private OrderCreate orderCreate;
@Mock
private OrderHelper orderHelper; // 此mock将被注入到orderCreate
@Before
public void initMocks() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void create() {
System.out.println("start mock...");
when(orderHelper.resolve()).thenReturn("null");
orderCreate.create();
}
} |
运行结果:
start mock...10null |
mock() / @Mock:创建一个mock;
spy() / @Spy:创建一个spy,提供了一种对真实对象操作的方法;
@InjectMocks:创建一个实例。被@Mock(或@Spy)注解创建的mock将被注入到用该实例中。注意: @InjectMocks标注的属性不能使用接口。
3 Mockito在Spring boot 框架中的使用
3.1 Spring Boot自带测试模块
Spring boot自身提供很多有用的工具类和注解用于测试应用,主要分两个模块:spring-boot-test包含核心组件,spring-boot-test-autoconfigure为测试提供自动配置。开发者只需要引用spring-boot-starter-test即可。它提供的测试模块中包含了Mockito。
Spring boot使用@MockBean和@SpyBean来定义Mockito的mock和spy。SpringBoot提供的@MockBean注解,用于为Applicatio nContext中的bean定义一个mock,你可以使用该注解添加新beans,或替换已存在的bean定义。该注解可直接用于测试类,也可用于测试类的字段,或用于@Configuration注解的类和字段。当用于字段时,创建mock的实例也会被注入。Mock beans每次调用完测试方法后会自动重置。
以代码举例:
@Componentpublic class MethodTest {
public String One(boolean flag){
System.err.println("coming.........");
String d = Two(flag);
Three();
System.err.println("result data is "+d);
return d;
}
public String Two(boolean flag){
System.err.println("coming.........two");
if(flag){
throw new IllegalAccessError();
}
return "two";
}
public void Three(){
System.err.println("coming.........three");
}
} |
测试类 @SpyBean
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class SpyTest{
@SpyBean
private MethodTest spyTest;
@Test
public void test3(){
when(spyTest.Two(false)).thenReturn("test");
System.err.println(spyTest.One(false));
}
} |
运行结果:
coming.........twocoming.........coming.........threeresult data is test
test |
测试类 @MockBean
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class MockTest{
@MockBean
private MethodTest mockTest;
@Test
public void test3(){
when(mockTest.One(false)).thenReturn("test");
System.err.println(mockTest.One(false));
}
} |
运行结果:
test |
3.2 Spring Boot使用原生Mockito
使用方式见第2部分。
4 总结
为了统一springBoot和spring项目对Mockito的配置方式,同时解决框架中Mybaties之Mapper动态代理的mock场景,建议统一使用xml文件配置的方式。