上一篇写到了使用@MockBean为Springboot 单元测试接口,可以看这一篇
Springboot Restful风格 接口单元测试_Mock
在正常情况下问题会解决,但是会碰到如下的情况
下面我们就根据之前的结论,完成后续的内容!
有时,我们的结果和拦截器并无关系,拦截器如果是正常使用,可能对测试的进行产生拦截作用,直接返回false , 导致无法进行的后续的步骤。此时我们可以进行如下的操作:
@MockBean
private TokenInterceptor interceptor;
我们知道@MockBean 会替换到已经注入到容器中的bean,替换为一个如下所示的对象
我们的拦截器同样是需要注入到容器中的,所以我们先用@MockBean对象替换,那么就无法调用到preHeader()等拦截器的方法,成功阻止了拦截器的调用。当然这里只是为了测试,在不修改业务代码的同时,还能使测试用例正确执行。
拦截器中包含登录,那么如果对后续内容没有影响,那么我们可以跳过拦截器的方式,可是如果拦截器里有对后续调用产生影响的操作,那么就无法直接跳过拦截器
我们可以采用下列的方式
添加对象头
MvcResult mvcResult = mockMvc.perform(
MockMvcRequestBuilders.post("/allocate")
.accept(MediaType.parseMediaType("application/json;charset=UTF-8"))
.content(strJson)
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization" , authorization)
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
通过添加Authorization的请求头,实现用户调用API的授权。此时我们就可以通过认证通过的方式,去通过拦截器的认证,最终达到核心的方式
前面提到了,我们的某些返回值可能不符合判定的要求而直接返回结果或者抛出异常,原因是被标注了@MockBean的类是无法实际调用到业务方法本身的(原因之前解释过了,增删改的方法不适应去测试修改数据),那么就存在一个问题,如果某个方法的返回值对后续结果会产生影响,比如如果返回结果为空,抛出Exception异常等操作,那么方法的测试就没有了意义。
这里补充一下之前没讲到的内容
所以如果你想替换的是容器内的对象,那么就使用@MockBean
那么如何构建呢?
@BeforeEach
public void setUp() throws Exception{
Mockito.when(roleService.list(Mockito.any())).thenAnswer((x)->{
UserRoleEntity userRoleEntity = new UserRoleEntity();
userRoleEntity.setUserId(1366290176789917698l);
List<UserRoleEntity> userRoleEntityList = new ArrayList<>();
userRoleEntityList.add(userRoleEntity);
return userRoleEntityList;
});
List<RoleEntity> roleEntityList = new ArrayList<>();
roleEntityList.add(new RoleEntity().setName("admin"));
Mockito.when(roleService.listByIds(Mockito.anySet())).thenReturn(roleEntityList);
}
要为roleService.listByIds方法构建返回值 ,Mockito.anySet()是对应的入参,这里入参可以填写具体的类型的value,也可以使用参数匹配器去匹配同类型所有参数(这里比较简单 就不过多赘述了)
Mockito.when().thenAnswer();
Mockito.when().thenReturn();
explain:
Mockito.when (mock.get(any())),thenReturn(null);
这里是想告诉我们,when是无法写入真实的类的,必须是被@MockBean 或者 @Mock 标注的类。也就是构建条件的前提是 @MockBean ,它控制当达到某个条件 when 的入参时,会返回某值
这样我们就为测试的接口构建了正确的返回结果,这里还需要强调,一般来说 增删改才去构建,如果是查询操作,没有特殊的要求,还是应该用真实的结果去。
注
这里多讲个方法:
Mockito.when(xxxService.getId(Mockito.anyLong())).thenCallRealMethod();
这个方法不如我们想象的美好,在容器中,使用它会带来很多问题,原因是它所有表达的RealMethod是会调用到真实的方法 而非MockBean创建的类,但是它并没有完成类的初始化,所以在调用真实的未经初始化的Service那看起来就是灾难!
好了,基本上测试的工作也能告一段落了,这样接口的基本功能都能测试到了!
希望能够有帮助,想收藏的收藏一下吧~
❤❤❤