@WebMvcTest下Spring Controller测试安全配置及视图断言问题排查
排查Spring MVC单元测试视图断言失败问题
咱们来一步步拆解你遇到的问题:测试返回200状态码,但ModelAndView为null,控制器的debug日志没打印,而且断言视图名时得到null。核心原因集中在测试请求的错误使用、断言方式错误,以及潜在的权限校验/异常处理问题上。
一、最直接的两个错误
1. 错误使用断言方法
你的控制器返回的是服务器端转发的视图名(return "companyInfo"),而不是重定向指令,但你用了redirectedUrl("companyInfo")断言——这个方法是用来校验重定向URL的,完全不匹配场景!应该用view().name("companyInfo")来断言视图名。
2. 请求属性未正确传递
看你第一个测试方法:
RequestBuilder request = get("/companyInfo") .requestAttr("someAccount", mockAccount); mockMvc.perform(get("/companyInfo")); // 这里没用你构建的request,重新发了空请求!
你构建了带有someAccount属性的请求对象,但实际执行时又重新创建了一个空请求,导致控制器里request.getAttribute("someAccount")拿到null,触发throw new Exception()。如果有全局异常处理器捕获了这个异常,就会返回200但没有视图,这也解释了为什么debug日志没打印(方法执行到抛出异常就终止了)。
二、修复后的测试代码示例
@Test @WithMockUser public void forwardsToCompanyInfoPageSuccessfully() throws Exception { // 准备测试数据 CompanyInfoDTO dto = new CompanyInfoDTO(); final Account mockAccount = new Account(); mockAccount.setId("12334"); // Mock依赖服务的行为 Mockito.when(companyService.getCompanyInfo(Mockito.any(Account.class))) .thenReturn(dto); Mockito.when(someAuthorizationService.hasRole(Constants.MY_ROLE)) .thenReturn(true); // 构建正确的请求,携带必要的属性 RequestBuilder request = get("/companyInfo") .requestAttr("someAccount", mockAccount); // 执行请求并做正确断言 mockMvc.perform(request) .andExpect(status().isOk()) .andExpect(view().name("companyInfo")) // 正确断言视图名 .andExpect(model().attributeExists("companyInformation")); // 可选:验证Model属性 }
三、额外排查点
如果修复后还是有问题,再检查这几个地方:
- 权限校验Mock是否生效:确认
@MockBean(name = "someService")的bean名称和@PreAuthorize里的@someService完全一致,Debug一下someAuthorizationService.hasRole是否被调用。 - SecurityConfiguration配置:检查是否有对
/companyInfo的特殊拦截规则,比如是否要求特定角色,或者是否被其他过滤器拦截。 - 全局异常处理器:如果控制器抛出的
Exception被@ControllerAdvice捕获并返回了空响应,也会导致ModelAndView为null,可以暂时注释异常处理器测试是否恢复正常。
内容的提问来源于stack exchange,提问作者user10685983
相关产品推荐
相关产品推荐

