单元测试如何模拟用户请求

错误

正当我高高兴兴写完后台c层的测试代码准备提交时,测试机器人报了不少401错误,把代码拉下来一看,原来当我写代码时,个人伙伴已经写好后台的拦截器了,只有绑定了token的用户才能访问后台,因此当我单元测试c层模拟请求时就会报错,
image.pngjson

由于个人模拟前台请求就像是一个没有登录的用户请求,通过拦截器必然是被拦截了下来。
image.pngdom

解决通过

一开始有点不知所错。咱们的模拟请求失败是由于后台在没有绑定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"));

    }

image.png
可是两次模拟请求并非同一个用户,咱们须要在第一次请求的时候获取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());

image.png
咱们也能够在mock方法里设置传入任一参数都返回true,这样咱们就不用在后续模拟请求中发送token了。测试

@Before
    public void loginUser() throws Exception {

      Mockito.when(this.userService.isLogin(Mockito.any())).thenReturn(true);
    }

总结

不断改进本身的解决办法,从中学到更多解决问题的方法,同时加深了对拦截器和token的了解。ui

相关文章
相关标签/搜索