我有一个演示过滤器来记录请求/响应主体并验证请求签名,如果签名错误,过滤器将重定向到我的错误控制器。我有一些测试用例来检查这个过滤器:
RestTemplate
RestTemplate
MockMvc
MockMvc
当我运行时,案例1,2,3是正确的。但案例4有一些问题。 我发现案例4已运行此代码,但它没有重定向到我的错误控制器。
RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher("/error/signError");
requestDispatcher.forward(requestWrapper, responseWrapper);
我是否使用MockMvc
的默认@Autowired
或使用MockMvcBuilders创建,此代码无效。
那么,我混淆了MockMvc
和RestTemplate
有多少不同,并且使用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();
}
}