摘要
“Mockito + junit + springboot” 搞定UT用例的复杂场景数据模拟
一、背景分析
-
目前主流的junit框架是junit4 和junit5,junit4的好处是资料和搭配使用的模块目前较多,junit5的优点是使用起来更加方便更加友好
-
在编写UT数据模拟这块junit的功能明显是不足的,因此我们常常还需要跟Mockito进行搭配,覆盖我们java项目开发的一些常见的场景(本文以目前主流开发的springboot场景进行讲解)
-
SpringBoot1.X版本默认使用的Junit4.X的版本,而SpringBoot2.X版本默认使用的junit5.X,说明主流的搭配也该如此,因此建议大家升级到springboot2.X也升级一下junit,短期方案可以在pom文件中指定junit使用版本为4.X
本文将对springboot1.X+junit4和springboot2.X+junit5这两种场景进行展开介绍,文章末尾附带代码链接。
二、springboot1.X+junit4
pom
spring-boot-starter-test 中默认集成了Mockito,则不需要额外引入。非springboot项目则引入方式如下:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
</dependency>
code
针对Springboot1.X的情况,mockito需要添加@RunWith(MockitoJUnitRunner.class)
如果使用的Junit + mockito联合测试,那应该使用的@RunWith(SpringJunit4ClassRunner.class), 这时候需要再添加mockito的初始化(可通过@Run public MockitoRule mockitoRule = MockitoJunit.rule();实现), 两种场景如下代码
package com.dreamkite.pg.controller;
@ActiveProfiles({"test"})
@SpringBootTest(classes = {MockitoJUnitRunner.class})
@RunWIth(SpringJunit4ClassRunner.class)
class AControllerTest {
@Autowired
@InjectMocks
private AController aController;
@Mock
private PersonService personService;
@Test
void hi() {
Mockito.doReturn("hjk").when(personService).hi();
Assert.assert("hjk", aController.hi());
}
}
第二种会启动springboot服务
package com.dreamkite.pg.controller;
@ActiveProfiles({"test"})
@SpringBootTest(classes = {UsePgApplication.class})
@RunWIth(SpringJunit4ClassRunner.class)
class AControllerTest {
@Run
public MockitoRule mockitoRule = MockitoJunit.rule();
@Autowired
@InjectMocks
private AController aController;
@Mock
private PersonService personService;
@Test
void hi() {
Mockito.doReturn("hjk").when(personService).hi();
Assert.assert("hjk", aController.hi());
}
}
代码补充说明:
@Mock创建的全部mock的对象,即在对具体的方法打桩前,mock对象的所有属性和方法全部置为空(0或null);
@injectMocks创建的对象,其内部的对象没有被@Mock进行注解的对象则为0或null,如果需要injectMocks注解的对象除了装配Mock的对象,其他内部对象能自动装配,则要跟@Autowired一起使用。
三、springboot2.X+junit5
junit5与junit4区别比较大,junit5使用了大量的jdk8特性、lamda表达式。
pom
spring-boot-starter-test 中默认集成了Mockito,则不需要额外引入。非springboot项目则引入方式如下:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>5.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.21.0</version>
<scope>test</scope>
</dependency>
Code
package com.dreamkite.pg.controller;
import com.dreamkite.pg.UsePgApplication;
import com.dreamkite.pg.service.PersonService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.junit.jupiter.api.Assertions.*;
@ActiveProfiles({"test"})
@SpringBootTest(classes = {UsePgApplication.class})
@ExtendWith(SpringExtension.class)
@ExtendWith({MockitoExtension.class})
class AControllerTest {
@Autowired
@InjectMocks
private AController aController;
@Mock
private PersonService personService;
@Test
void hi() {
Mockito.doReturn("hjk").when(personService).hi();
assertEquals("hjk", aController.hi());
}
}
见github链接:https://github.com/junkaitongxue/LearnSpringBoot/blob/main/usePostgres/src/test/java/com/dreamkite/pg/controller/AControllerTest.java
四、相关链接:
- Spring依赖注入与mock
- 使用Junit + Mockito实践单元测试
- Mockito框架@Mock, @InjectMocks注解使用
- 如何在Junit中使用@InjectMocks和@Autowired注释
(以上内容为DreamKite本人原创,转载请附上原文链接)