在我的测试中使用mockmvc时,RequestDispatcher不起作用

时间:2017-09-20 02:08:01

标签: java spring-mvc spring-boot

我有一个演示过滤器来记录请求/响应主体并验证请求签名,如果签名错误,过滤器将重定向到我的错误控制器。我有一些测试用例来检查这个过滤器:

  1. 使用RestTemplate
  2. 发布正确的签名
  3. 使用RestTemplate
  4. 发布错误的签名
  5. 使用MockMvc
  6. 发布正确的签名
  7. 使用MockMvc
  8. 发布错误的签名

    当我运行时,案例1,2,3是正确的。但案例4有一些问题。 我发现案例4已运行此代码,但它没有重定向到我的错误控制器。

    RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher("/error/signError");
    requestDispatcher.forward(requestWrapper, responseWrapper);
    

    我是否使用MockMvc的默认@Autowired或使用MockMvcBuilders创建,此代码无效。 那么,我混淆了MockMvcRestTemplate有多少不同,并且使用MockMvc可以使RequestDispatcher工作?

    过滤器代码:

    @Component
    public class ApiFilter extends OncePerRequestFilter {
    
    private static final Logger LOG = LoggerFactory.getLogger(ApiFilter.class);
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
    
        String requestId = UUID.randomUUID().toString();
    
        String requestBody = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
    
        LOG.info("request id [{}] requset body [{}]", requestId, requestBody);
        ApiRequestWrapper requestWrapper = null;
        ApiResponseWrapper responseWrapper = null;
        try {
            requestWrapper = new ApiRequestWrapper(requestId, request, requestBody);
            responseWrapper = new ApiResponseWrapper(requestId, response);
            System.out.println(request.getRequestURI());
            System.out.println(request.getRequestURL());
            System.out.println(request.getPathInfo());
            System.out.println(getServletContext());
            if (StringUtils.equalsIgnoreCase(request.getHeader(ApiConstant.HEAD_SIGN), DigestUtils.md5Hex(requestBody + ApiConstant.API_TOKEN))) {
                filterChain.doFilter(requestWrapper, responseWrapper);
            } else {
                // redirect to error response
                RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher("/error/signError");
                requestDispatcher.forward(requestWrapper, responseWrapper);
            }
    
        } finally {
            LOG.info("request id [{}] response body [{}]", requestId, responseWrapper);
        }
    }
    }
    

    和我的测试用例一样。

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
    @AutoConfigureMockMvc
    public class LoginContorllerTest {
    
    @Autowired ObjectMapper objectMapper;
    
    //@Autowired
    MockMvc mockMvc;
    
    @Autowired TestRestTemplate restTemplate;
    
    @Autowired WebApplicationContext webApplicationContext;
    
    @Autowired ApiFilter apiFilter;
    
    @Before
    public void init() throws Exception {
        MockFilterConfig filterConfig = new MockFilterConfig(webApplicationContext.getServletContext(), "apiFilter");
        apiFilter.init(filterConfig);
        this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilter(apiFilter, "/api/*").build();
    }
    
    @Test
    public void mockTest() throws Exception {
        System.out.println("mockTest");
        LoginParam param = new LoginParam();
        param.setUsername("test");
        param.setPassword("123456");
        String requestBody = objectMapper.writeValueAsString(param);
        String sign = DigestUtils.md5Hex(requestBody + ApiConstant.API_TOKEN);
        String contentAsString = mockMvc
                .perform(post("/api/login").header(ApiConstant.HEAD_SIGN, sign).contentType(MediaType.APPLICATION_JSON_UTF8).content(requestBody))
                .andExpect(status().isOk())
                .andReturn()
                .getResponse()
                .getContentAsString();
        // please forgive me using this way in the demo
        System.out.println(contentAsString);
        System.out.println();
    }
    
    @Test
    public void mockSignErrorTest() throws Exception {
        System.out.println("mockSignErrorTest");
        LoginParam param = new LoginParam();
        param.setUsername("test");
        param.setPassword("123456");
        String requestBody = objectMapper.writeValueAsString(param);
        String contentAsString = mockMvc
                .perform(post("/api/login").header(ApiConstant.HEAD_SIGN, "12254548858").contentType(MediaType.APPLICATION_JSON_UTF8).content(requestBody))
                .andReturn()
                .getResponse()
                .getContentAsString();
        System.out.println(contentAsString);
        System.out.println();
    }
    
    @Test
    public void restTest() throws Exception {
        System.out.println("restTest");
        LoginParam param = new LoginParam();
        param.setUsername("test");
        param.setPassword("123456");
        String requestBody = objectMapper.writeValueAsString(param);
        String sign = DigestUtils.md5Hex(requestBody + ApiConstant.API_TOKEN);
        HttpHeaders headers = new HttpHeaders();
        headers.add(ApiConstant.HEAD_SIGN, sign);
    
        HttpEntity<LoginParam> httpEntity = new HttpEntity<LoginParam>(param, headers);
        ResponseEntity<String> result = this.restTemplate.exchange("/api/login", HttpMethod.POST, httpEntity, String.class);
        System.out.println(result.getBody());
        System.out.println();
    }
    
    @Test
    public void restSignErrorTest() throws Exception {
        System.out.println("restSignErrorTest");
        LoginParam param = new LoginParam();
        param.setUsername("test");
        param.setPassword("123456");
        HttpHeaders headers = new HttpHeaders();
        headers.add(ApiConstant.HEAD_SIGN, "123456789");
    
        HttpEntity<LoginParam> httpEntity = new HttpEntity<LoginParam>(param, headers);
        ResponseEntity<String> result = this.restTemplate.exchange("/api/login", HttpMethod.POST, httpEntity, String.class);
        System.out.println(result.getBody());
        System.out.println();
    }
    }
    

0 个答案:

没有答案