You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MockMvc测试AppUserController时ResourceNotFoundException抛出异常问题排查

问题排查与解决方案

核心问题分析

你遇到的NestedServletException是因为Spring MVC的全局异常处理器未正确捕获并处理ResourceNotFoundException,导致异常直接冒泡到MockMvc层面,而非返回预期的404响应。以下是具体排查点和解决办法:

排查点1:全局异常处理器是否被测试上下文加载

如果测试类使用@WebMvcTest(AppUserController.class),该注解默认仅扫描指定控制器类,不会自动加载@ControllerAdvice标记的全局异常处理器。

解决办法:
在测试类上添加@Import(GlobalExceptionHandler.class),手动将异常处理器纳入测试上下文:

@WebMvcTest(AppUserController.class)
@Import(GlobalExceptionHandler.class)
class AppUserControllerTest {
    // 测试代码
}

若使用@SpringBootTest,需确保GlobalExceptionHandler所在包在组件扫描范围内(如与主启动类同包或子包)。

排查点2:MockMvc构建模式是否注册了异常处理器

如果手动构建MockMvc(如使用MockMvcBuilders.standaloneSetup),该模式不会自动识别@ControllerAdvice,需手动注册异常处理器:

修正前:

mockMvc = MockMvcBuilders.standaloneSetup(controller).build();

修正后:

mockMvc = MockMvcBuilders.standaloneSetup(controller)
        .setControllerAdvice(new GlobalExceptionHandler()) // 手动注册异常处理器
        .build();

排查点3:全局异常处理器的捕获逻辑是否正确

检查GlobalExceptionHandler是否准确捕获ResourceNotFoundException并返回404:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<String> handleResourceNotFound(ResourceNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
    }
}

确保@ExceptionHandler的参数类型是精确的ResourceNotFoundException,避免用父类(如RuntimeException)覆盖导致优先级问题。

排查点4:Mock对象的注入是否正确

确认测试中UserDetailsServiceImpl的mock已正确注入控制器:

  • 使用@MockBean标记UserDetailsServiceImpl,确保控制器调用的是该mock实例:
@WebMvcTest(AppUserController.class)
@Import(GlobalExceptionHandler.class)
class AppUserControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserDetailsServiceImpl userDetailsService;

    @Test
    void shouldReturn404WhenUserNotFound() throws Exception {
        // 模拟抛出异常
        when(userDetailsService.findAppUserById(anyLong()))
                .thenThrow(new ResourceNotFoundException("User not found"));

        // 执行请求并验证响应
        mockMvc.perform(get("/api/users/1"))
                .andExpect(status().isNotFound())
                .andExpect(content().string("User not found"));
    }
}

避免手动创建控制器实例并注入mock,确保Spring管理的控制器使用@MockBean提供的对象。

验证步骤

  1. 先单独验证全局异常处理器功能:启动应用后手动调用接口,确认是否返回404,排除异常处理器本身的问题。
  2. 检查测试类上下文配置,确保所有依赖bean都被正确加载。
  3. 调试测试,确认userDetailsService.findAppUserById确实抛出了ResourceNotFoundException,且控制器没有额外的try-catch吞掉异常。

内容的提问来源于stack exchange,提问作者Demir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 00:54:53