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

Spring Boot登录接口集成测试:BadCredentialsException断言失败问题

Spring Boot集成测试:密码不匹配场景下BadCredentialsException抛出但断言失败的解决办法

问题原因

Spring Security过滤器链中,AuthFilter(继承自AbstractAuthenticationProcessingFilter)抛出的BadCredentialsException会被ExceptionTranslationFilter捕获并处理,直接转换为HTTP 401响应,不会将原始异常传递到MockMvc的resolvedException对象中。你通过result.getResolvedException()获取的是控制器层或全局异常处理器处理后的异常,而此处异常在过滤器阶段就被拦截处理,因此该方法无法拿到你抛出的BadCredentialsException,导致断言失败。

解决方案

方案1:验证响应状态码(推荐)

既然Spring Security已将异常转换为标准401响应,直接验证状态码即可,若有自定义错误响应体,还可同时验证响应内容:

@DisplayName("密码不匹配时返回401状态码")
@Test
void shouldReturn401_WhenPasswordDoesntMatch() throws Exception {
    LoginDTO login = new LoginDTO(USER_JWT, INVALID);
    String json = objectMapper.writeValueAsString(login);

    mockMvc.perform(post(LOGIN_ENDPOINT)
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(json))
            .andExpect(status().isUnauthorized());
    // 若系统返回自定义错误响应,可添加如下断言(示例):
    // .andExpect(jsonPath("$.error").value("Password is wrong."));
}

方案2:通过Security上下文断言异常

如果必须验证抛出的是BadCredentialsException,可借助Spring Security测试扩展,从请求属性中获取认证异常:

@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;

@BeforeEach
void setUp() {
    mockMvc = MockMvcBuilders.webAppContextSetup(context)
            .apply(SecurityMockMvcConfigurers.springSecurity())
            .build();
}

@DisplayName("密码不匹配时抛出BadCredentialsException")
@Test
void shouldThrowBadCredentialsException_WhenPasswordDoesntMatch() throws Exception {
    LoginDTO login = new LoginDTO(USER_JWT, INVALID);
    String json = objectMapper.writeValueAsString(login);

    mockMvc.perform(post(LOGIN_ENDPOINT)
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(json))
            .andExpect(status().isUnauthorized())
            .andExpect(result -> {
                // 从Security存储的请求属性中获取认证异常
                AuthenticationException authException = 
                    (AuthenticationException) result.getRequest().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
                Assertions.assertTrue(authException instanceof BadCredentialsException);
            });
}

额外说明

你的/login控制器方法在密码不匹配场景下不会被执行,因为请求先经过AuthFilter,过滤器抛出异常后直接被Spring Security处理,请求不会到达控制器层,因此控制器返回的ResponseEntity.ok()在此场景下不会生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:17:39