通过在类上面使用 @AutoConfifigureMockMvc 注解,然后在类成员变量或者方法参数上注入MockMvc 实例,就可以完成对 Spring MVC 接口的 Mock 测试。
下面是一个基于默认 Mock 环境的测试用例:
@SpringBootTest
@AutoConfigureMockMvc
class MockMvcTests {
@Test
public void getUserTest(@Autowired MockMvc mvc) throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/user/get?username={username}", "test"))
.andExpect(status().isOk())
.andExpect(content().string("{\"code\":0,\"msg\":\"ok\",\"
data\":\"test\"}"));
}
}
测试当前应用下的 /user/get 接口,传入对应的用户名参数,最后检查请求状态是否OK(200),响应的内容是否和预期一致,测试结果如下图所示。
单元测试通过,从执行日志可以看到,它并未启动真实的 Web 环境来测试,而是使用 Mock 环境测试的。
Mock 组件测试
某些时候可能还需要模拟一些组件,比如某些服务只有上线之后才能调用,在开发阶段不可用,这时就需要 Mock 模拟测试了,提供各种模拟组件以完成测试。
Spring Boot 提供了一个 @MockBean 注解,可为 Spring 中的 Bean 组件定义基于 Mockito 的Mock 测试,它可以创建一个新 Bean 以覆盖 Spring 环境中已有的 Bean,它可以用在测试类、成员变量上,或者 @Confifiguration 配置类、成员变量上,被模拟的 Bean 在每次测试结束后自动重置。
假现现在有一个远程的服务 userService,本地不能调用,现在进行 Mock 测试,如以下使用示例所示。
@SpringBootTest
class MockBeanTests {
// @Autowired
// private UserService userService;
@MockBean
private UserService userService;
@Test
public void countAllUsers() {
BDDMockito.given(this.userService.countAllUsers()).willReturn(88);
assertThat(this.userService.countAllUsers()).isEqualTo(88);
}
}
这里的 @MockBean 注解使用在 UserService 变量上,表明这个userService实例在当前测试用例中是被 Mock 覆盖的,如果要模拟的 Bean 有多个,则可以使用@Qualififier注解指定,然后通过Mockito 提供的代理工具类方法创建模拟返回数据,运行该服务的测试方法,当模拟数据和预期结果一致时才会测试通过。
这里通过 BDDMockito 工具类模拟 userService#countAllUsers方法并让它返回统计的用户总数(88),最后检查该方法的返回值是否和预期一致,测试结果如下图所示。
单元测试通过,也可以使用 @SpyBean 注解代替 @MockBean 注解,两者的区别是:
● @SpyBean—如果没有提供 Mockito 代理方法,则会调用真实的 Bean 来获取数据。
● @MockBean—不管有没有提供 Mockito 代理方法,都会调用 Mock 的 Bean 来获取数据。
@MockBean、@SpyBean 注解既可作用于 Mock 环境,也可作用于真实环境,它只是用来模拟、替换环境中指定的 Bean 而已,但不能用于模拟在应用上下文刷新期间 Bean 的行为,因为在执行测试用例时应用上下文已经刷新完成了,所以不可能再去模拟了,这种情况下建议使用 @Bean 方法来创建模拟配置。