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

移除WebSecurityConfigurerAdapter后WebMvcTest失效,测试报错求助

替换WebSecurityConfigurerAdapter后WebMvcTest的问题排查与解决

升级Spring Security配置、替换已弃用的WebSecurityConfigurerAdapter后,应用通过Postman测试运行正常,但大量标注@WebMvcTest的测试用例报错,以下是典型问题及解决办法:


错误1:AuthTokenFilterTest抛出UnsatisfiedDependencyException

错误栈核心信息:
UnsatisfiedDependencyException: Error creating bean with name 'com.example.demo.security.AuthTokenFilterTest': Unsatisfied dependency expressed through field 'authTokenFilter'; nested exception is NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.security.AuthTokenFilter' available: expected at least 1 bean which qualifies as autowire candidate.

测试代码片段:

@WebMvcTest(AuthTokenFilter.class)
public class AuthTokenFilterTest {
    @Autowired
    private AuthTokenFilter authTokenFilter;

    // 测试逻辑...
}

错误2:RegisterControllerTest中AuthController创建失败

错误栈核心信息:
UnsatisfiedDependencyException: Error creating bean with name 'com.example.demo.controller.AuthController': Unsatisfied dependency expressed through field 'passwordEncoder'; nested exception is NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.crypto.password.PasswordEncoder' available: expected at least 1 bean which qualifies as autowire candidate.

测试代码片段:

@WebMvcTest(RegisterController.class)
public class RegisterControllerTest {
    @Autowired
    private MockMvc mockMvc;

    // 测试逻辑...
}

新旧SecurityConfig代码对比

旧配置(基于WebSecurityConfigurerAdapter)

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() {
        return new AuthTokenFilter();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 原有HttpSecurity配置
    }
}

新配置(替换WebSecurityConfigurerAdapter)

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/**").permitAll()
                .anyRequest().authenticated()
            );

        http.authenticationProvider(authenticationProvider());
        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }

    // 问题点:私有方法未声明为Bean
    private AuthTokenFilter authenticationJwtTokenFilter() {
        return new AuthTokenFilter();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

问题原因及解决方案

针对错误1:AuthTokenFilter无法被注入

原因:新配置中authenticationJwtTokenFilter()是私有方法,且未添加@Bean注解,导致Spring容器中没有该类型的Bean实例,测试类无法自动注入。

解决办法:将该方法改为公共方法并添加@Bean注解:

@Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
    return new AuthTokenFilter();
}

针对错误2:PasswordEncoder无法被注入到AuthController

原因:@WebMvcTest注解默认只会加载控制器层相关的Bean,不会自动加载Security配置类中的Bean。如果AuthController依赖PasswordEncoder,测试环境中就会缺少该Bean。

解决办法二选一:

  1. 在测试类中手动声明PasswordEncoder Bean:
@WebMvcTest(RegisterController.class)
public class RegisterControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 测试逻辑...
}
  1. 在测试类中通过@Import引入SecurityConfig:
@WebMvcTest(RegisterController.class)
@Import(SecurityConfig.class)
public class RegisterControllerTest {
    @Autowired
    private MockMvc mockMvc;

    // 测试逻辑...
}

如果只需要PasswordEncoder,也可以单独导入包含该Bean的配置类,避免加载不必要的Security组件。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:21:01