
MockMvc 单元测试中,当控制器方法抛出自定义异常(如 ResourceNotFoundException)时,若未正确注册 @ControllerAdvice 异常处理器,会导致测试失败并抛出嵌套的 NestedServletException。关键在于通过 standaloneSetup().setControllerAdvice() 显式注入异常处理器。
mockmvc 单元测试中,当控制器方法抛出自定义异常(如 resourcenotfoundexception)时,若未正确注册 @controlleradvice 异常处理器,会导致测试失败并抛出嵌套的 nestedservletexception。关键在于通过 `standalonesetup().setcontrolleradvice()` 显式注入异常处理器。
在使用 @WebMvcTest 进行控制器层测试时,Spring Boot 默认不会自动加载 @ControllerAdvice 组件(如 AppExceptionHandler),尤其当采用 standaloneSetup 手动构建 MockMvc 实例时——这正是本问题的根本原因。
当前测试代码中,@BeforeEach setUp() 方法重建了 MockMvc,但仅调用 MockMvcBuilders.standaloneSetup(underTest).build(),未注册任何异常处理器。因此,当 findAppUserById() 抛出 ResourceNotFoundException 后,Spring MVC 无法找到匹配的 @ExceptionHandler,直接将原始异常包装为 NestedServletException 并中断请求流程,导致断言 status().isNotFound() 失败。
✅ 正确做法是:显式将 AppExceptionHandler 注入到 standaloneSetup 中:
@BeforeEach
void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(underTest)
.setControllerAdvice(new AppExceptionHandler()) // ✅ 关键修复:注册全局异常处理器
.build();
}⚠️ 注意事项:
- setControllerAdvice(...) 接收一个或多个 @ControllerAdvice 实例(支持类、对象或 Class<?>),此处传入 new AppExceptionHandler() 即可;
- 若项目中存在多个异常处理器(如 ValidationExceptionHandler),可链式调用 .setControllerAdvice(a, b, c);
- 确保 AppExceptionHandler 类位于测试类可访问包路径下,且无依赖注入冲突(本例中 AppExceptionHandler 无构造依赖,可安全实例化);
-
避免同时使用 @WebMvcTest 和 standaloneSetup 的冗余配置:当前类上标注了 @WebMvcTest(useDefaultFilters = false),但又手动 @Autowired MockMvc 并在 setUp() 中重置,这会造成配置冲突。建议二选一:
- ✅ 推荐方式(简洁可靠):移除 @Autowired MockMvc 和 setUp() 中的重建逻辑,仅保留 @WebMvcTest,并通过 @Import(AppExceptionHandler.class) 显式导入异常处理器:
@WebMvcTest(
controllers = AppUserController.class,
useDefaultFilters = false
)
@Import(AppExceptionHandler.class) // ✅ 让@WebMvcTest自动扫描并注册
class AppUserControllerTest {
// ... 其他字段保持不变(@Mock, @InjectMocks等)
@Autowired
private MockMvc mockMvc; // ✅ 直接注入,无需手动构建
// 删除 setUp() 方法
}- ❌ 不推荐:混合 @WebMvcTest + standaloneSetup —— 容易引发 Bean 加载不一致、AOP 失效、异常处理器未生效等问题。
此外,确保 ResourceNotFoundException 的序列化兼容性:由于 ApplicationException 使用了 @JsonIgnoreProperties 忽略了 stackTrace 等字段,而 ObjectMapper 在反序列化响应体时需能正确映射 JSON 字段(如 resultCode, message, httpStatusCode, thrownAt)。建议在测试中验证 JSON 响应结构是否符合预期,例如:
// 可选:打印响应内容辅助调试
System.out.println("Response body: " + resultContent);总结:MockMvc 测试中自定义异常未被捕获,90% 源于 @ControllerAdvice 未被正确注册。优先采用 @WebMvcTest + @Import 方式,语义清晰、配置轻量、与 Spring Boot 测试约定完全对齐;若必须使用 standaloneSetup,务必调用 setControllerAdvice() 显式挂载处理器。


















