正当我高高兴兴写完后台c层的测试代码准备提交时,测试机器人报了不少401错误,把代码拉下来一看,原来当我写代码时,个人伙伴已经写好后台的拦截器了,只有绑定了token的用户才能访问后台,因此当我单元测试c层模拟请求时就会报错,json
由于个人模拟前台请求就像是一个没有登录的用户请求,通过拦截器必然是被拦截了下来。dom
一开始有点不知所错。咱们的模拟请求失败是由于后台在没有绑定token的状况下请求了其余接口,而咱们的拦截器也没有发token给模拟请求。咱们正常要使用系统的话要先登陆,第一次登陆的话后台会发送一个token给前台并与用户绑定,之后就会带着后台发来的token去请求。
因此首先模拟一下正常的登陆流程。创造一个方法loginUser()
,在方法上添加注释@Before
,用于在每一个测试方法前执行。在这个先新建一个用户用来当咱们的模拟用户,咱们用这个用户的username和password来进行登陆,而后在进行请求。函数
@Test public void loginUser() throws Exception { String url = "/user/login"; String username = RandomString.make(6); String password = RandomString.make(6); JSONObject jsonObject = new JSONObject(); jsonObject.put("username", username); jsonObject.put("password", password); // 当以参数username, password调用userService.login方法时,返回true Mockito.when(this.userService.login(username, password)).thenReturn(true); // 触发C层并断言返回值 this.mockMvc.perform(MockMvcRequestBuilders.post(url) .contentType(MediaType.APPLICATION_JSON_UTF8) .content(jsonObject.toJSONString())) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.content().string("true")); }
可是两次模拟请求并非同一个用户,咱们须要在第一次请求的时候获取token并保存用户,在后续请求携带token发出模拟请求。这就须要引入request类。
上述方法太麻烦了,在学长的建议下,研究拦截器原理,发现拦截器经过isLogin()函数里判断token来判断这个用户是否登录过,若是把isLogin方法mock一下,让他永远返回true就不管传什么token就均可以不被拦截了。post
@Before public void loginUser() throws Exception { Mockito.when(this.userService.isLogin(Mockito.any(String.class))).thenReturn(true); }
可是只是在mock方法里规定传入string类型是不行的,咱们模拟请求默认token是null,因此咱们应该在模拟请求时加入header的token信息,随意一个字符串就好。单元测试
this.mockMvc.perform( MockMvcRequestBuilders.get(url) .header("auth-token", "key") .param("page", "1") .param("size", "2")) .andExpect(MockMvcResultMatchers.status().isOk());
咱们也能够在mock方法里设置传入任一参数都返回true,这样咱们就不用在后续模拟请求中发送token了。测试
@Before public void loginUser() throws Exception { Mockito.when(this.userService.isLogin(Mockito.any())).thenReturn(true); }
不断改进本身的解决办法,从中学到更多解决问题的方法,同时加深了对拦截器和token的了解。ui