前言
在功能开发完成后,虽然有专门的测试人员,但开发人员自身也要进行单元测试。
一般公司对BUG率和单元测试覆盖率都会有一定的要求,所以做好单元测试还是很有必要的。
后端提供的都是接口,本文使用MockMvc模拟接口进行测试。
具体实现
Maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
复制代码
为了防止测试对真实数据库数据产生影响,这里使用H2数据库,并进行参数配置。
参数配置
spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:test;MODE=MYSQL;
schema: classpath:sqls/sys.sql
main:
banner-mode: off
mybatis:
mapper-locations: classpath*:sql-mappers/**/*.xml
复制代码
- spring.datasource.schema 指定建表语句文件
- mybatis.mapper-locations 指定Mapper文件
示例
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
@Autowired
private MockMvc mvc;
private static Gson gson = new GsonBuilder().serializeNulls().create();
@Test
@SqlGroup({
@Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, value = "classpath:h2/user/init-data.sql"),
@Sql(executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, value = "classpath:h2/user/clean-data.sql")
})
void getUser() throws Exception {
// 模拟GET请求
mvc.perform(get("/user/1")
// 请求参数类型
.contentType(MediaType.APPLICATION_JSON_UTF8)
// 接收参数类型
.accept(MediaType.APPLICATION_JSON_UTF8))
// 结果验证
.andExpect(status().isOk())
.andExpect(jsonPath("code").value(200))
.andExpect(jsonPath("data").exists())
.andExpect(jsonPath("$['data']['account']").value("zhuqc1"))
.andExpect(jsonPath("$['data']['password']").value("password"))
.andExpect(jsonPath("$['data']['nickname']").value("zhuqc1"))
.andExpect(jsonPath("$['data']['email']").value("zqc@zqc.com"))
.andExpect(jsonPath("$['data']['phone']").value("13345678901"))
// 结果处理器
.andDo(MockMvcResultHandlers.print());
}
@Test
@SqlGroup({
@Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, value = "classpath:h2/user/init-data.sql"),
@Sql(executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, value = "classpath:h2/user/clean-data.sql")
})
void getUser2() throws Exception {
// 模拟GET请求,并返回结果
MvcResult result = mvc.perform(get("/user/1")
.accept(MediaType.APPLICATION_JSON_UTF8))
.andReturn();
MockHttpServletResponse response = result.getResponse();
JsonObject apiResult = JsonParser.parseString(response.getContentAsString()).getAsJsonObject();
JsonObject data = apiResult.getAsJsonObject("data").getAsJsonObject();
// 断言验证数据
Assertions.assertEquals(response.getStatus(), HttpStatus.OK.value());
Assertions.assertEquals(data.get("account").getAsString(), "zhuqc1");
Assertions.assertEquals(data.get("password").getAsString(), "password");
Assertions.assertEquals(data.get("nickname").getAsString(), "zhuqc1");
Assertions.assertEquals(data.get("email").getAsString(), "zqc@zqc.com");
Assertions.assertEquals(data.get("phone").getAsString(), "13345678901");
}
@Test
@SqlGroup({
@Sql(executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, value = "classpath:h2/user/clean-data.sql")
})
void addUser() throws Exception {
User user = new User();
user.setAccount("zhuqc1");
user.setPassword("password");
user.setNickname("zhuqc1");
user.setEmail("zqc@zqc.com");
user.setPhone("13345678901");
// 模拟POST请求
mvc.perform(post("/user")
// 请求参数类型
.contentType(MediaType.APPLICATION_JSON_UTF8)
// 接收参数类型
.accept(MediaType.APPLICATION_JSON_UTF8)
// 请求参数
.content(gson.toJson(user)))
// 结果验证
.andExpect(status().isOk())
.andExpect(jsonPath("code").value(200))
.andExpect(jsonPath("data").value(1));
}
}
复制代码
-
@SpringBootTest 指定测试类在SpringBoot环境下运行
-
@AutoConfigureMockMvc 用于自动配置MockMvc,配置后MockMvc类可以直接注入
-
@SqlGroup 指定测试方法执行前后的SQL语句
比如,可以在测试方法执行前,初始化数据;在测试方法执行后,清除数据。
MockMvc
MockMvc是接口测试的主入口,核心方法perform(RequestBuilder),
会自动执行SpringMVC的流程并映射到相应的控制器执行处理,方法返回值是ResultActions。
ResultActions
- andExpect 添加ResultMatcher验证规则,验证执行结果是否正确。
- andDo 添加ResultHandler结果处理器,比如打印结果到控制台。
- andReturn 返回MvcResult执行结果,可以对结果进行自定义验证。
MockMvcResultMatchers
用于验证执行结果是否正确,详见测试方法getUser()。
MockMvcResultHandlers
结果处理器,表示要对结果做点什么事情。详见测试方法getUser()。
比如使用MockMvcResultHandlers.print()打印响应结果信息到控制台。如下:
MvcResult
单元测试执行结果,可以对结果进行自定义验证,详见测试方法getUser2()。
近期评论