MockMvc测试自定义登录接口:转发成功后响应体为空问题
解决MockMvc测试自定义登录转发后响应体为空的问题
问题核心
MockMvc默认不会自动跟进转发请求,只会记录转发URL,因此你能验证状态码和转发路径,但拿不到/loggedin端点返回的响应体。
三种可行解决方案
1. 手动跟进转发请求
先执行登录请求获取转发信息,再单独构造并执行转发目标的请求,以此拿到响应体:
// 执行登录请求,确认转发行为 MvcResult loginResult = mockMvc.perform(post("/login") .contentType(MediaType.APPLICATION_JSON) .content("{\"username\":\"test\",\"password\":\"test\",\"rememberMe\":true}")) .andExpect(status().isOk()) .andExpect(forwardedUrl("/loggedin")) .andReturn(); // 构造转发请求并验证响应 MockHttpServletRequest forwardedReq = loginResult.getRequest().getRequestDispatcher("/loggedin").getRequest(); mockMvc.perform(request(forwardedReq)) .andExpect(status().isOk()) .andExpect(content().json("{\"status\":\"success\",\"message\":\"Logged in successfully\"}"));
2. 调整SuccessHandler逻辑,直接返回响应
如果/loggedin仅用于返回登录成功的JSON,完全可以在JsonAuthenticationSuccessHandler里直接生成响应,省去转发步骤:
@Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { response.setContentType(MediaType.APPLICATION_JSON_VALUE); new ObjectMapper().writeValue(response.getWriter(), new LoginResponse("success", "Logged in successfully")); }
测试时就能直接断言响应体:
mockMvc.perform(post("/login") .contentType(MediaType.APPLICATION_JSON) .content("{\"username\":\"test\",\"password\":\"test\",\"rememberMe\":true}")) .andExpect(status().isOk()) .andExpect(content().json("{\"status\":\"success\",\"message\":\"Logged in successfully\"}"));
3. 配置MockMvc自动跟进转发
创建MockMvc时启用dispatchOptions(true),让它自动处理转发并返回最终响应:
@Autowired private WebApplicationContext webApplicationContext; private MockMvc mockMvc; @BeforeEach void setUp() { mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) .dispatchOptions(true) .build(); }
之后测试代码无需额外处理,直接断言响应体即可。
内容的提问来源于stack exchange,提问作者theMyth
相关产品推荐
相关产品推荐

