Spring Test中404请求未重定向到Swagger页面的问题排查
问题分析与解决方案
问题根源
你遇到的测试失败确实和MockMvc的特性有关:MockMvc直接调用Spring MVC的DispatcherServlet,不会经过Servlet容器的错误处理流程,所以你配置的WebServerFactoryCustomizer中的容器级ErrorPage规则不会生效。从控制台输出也能看出,请求被ResourceHttpRequestHandler处理后直接返回404,没有触发重定向逻辑。
两种解决方案
方案1:启动真实Servlet容器测试
改用@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)启动真实的Servlet容器,此时容器级的ErrorPage配置会生效,用TestRestTemplate或WebTestClient替代MockMvc:
用TestRestTemplate的测试代码
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(classes = { MyProjectContext.class }) class MyProjectErrorControllerTest { @Autowired private TestRestTemplate restTemplate; @Test void errorEnpointShouldRedirectToSwaggerPage() { ResponseEntity<Void> response = restTemplate.getForEntity("/dfhdfth", Void.class); // 验证状态码为302重定向 assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FOUND); // 验证重定向目标URL assertThat(response.getHeaders().getLocation().toString()).endsWith(Endpoints.SWAGGER); } }
用WebTestClient的测试代码
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(classes = { MyProjectContext.class }) class MyProjectErrorControllerTest { @Autowired private WebTestClient webTestClient; @Test void errorEnpointShouldRedirectToSwaggerPage() { webTestClient.get().uri("/dfhdfth") .exchange() .expectStatus().isFound() .expectHeader().location(Endpoints.SWAGGER); } }
方案2:改用Spring MVC层面的ErrorController
移除容器级的ErrorPage配置,改用Spring MVC的ErrorController实现重定向逻辑,这样MockMvc可以直接识别并处理:
修改配置类
@Configuration public class MyProjectContext implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController(Endpoints.NOT_FOUND) .setViewName("redirect:" + Endpoints.SWAGGER); } // 替换容器级ErrorPage为Spring MVC的ErrorController @Bean public ErrorController errorController(DefaultErrorAttributes errorAttributes) { return new BasicErrorController(errorAttributes) { @Override public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { HttpStatus status = getStatus(request); if (status == HttpStatus.NOT_FOUND) { // 返回302重定向到Swagger页面 return ResponseEntity.status(HttpStatus.FOUND) .header(HttpHeaders.LOCATION, Endpoints.SWAGGER) .build(); } // 其他错误状态码沿用默认处理 return super.error(request); } }; } }
修改后的MockMvc测试代码
此时原有的MockMvc测试可以正常运行,只需补充状态码验证:
@SpringBootTest @ContextConfiguration(classes = { MyProjectContext.class }) @AutoConfigureMockMvc class MyProjectErrorControllerTest { @Autowired private MockMvc mockMvc; @Test void errorEnpointShouldRedirectToSwaggerPage() throws Exception { mockMvc.perform(get("/dfhdfth")) .andExpect(status().isFound()) // 验证302状态码 .andExpect(redirectedUrl(Endpoints.SWAGGER)); } }
总结
- 若要验证容器级的错误页逻辑,必须启动真实Servlet容器,用TestRestTemplate/WebTestClient测试;
- 若想继续用MockMvc,需将重定向逻辑转移到Spring MVC层面的ErrorController中。
内容的提问来源于stack exchange,提问作者Kira Resari
相关产品推荐
相关产品推荐

