如何在 Spring Security Bean 中模拟自定义 UserService 详细信息以进行单元测试?

Posted

技术标签:

【中文标题】如何在 Spring Security Bean 中模拟自定义 UserService 详细信息以进行单元测试?【英文标题】:How to mock custom UserServiceDetails in SpringSecurity Bean for unit-testing? 【发布时间】:2020-02-09 16:46:03 【问题描述】:

我有Spring Boot 应用程序启用了基本身份验证。 UserServiceDetails 从数据库消耗。出于单元测试的目的,我想模拟它,因此数据将从其他地方使用。

我该怎么做?

我的问题不是如何模拟 UserServiceDetails 本身,而是如何模拟我可以使用它来测试具有基本身份验证的控制器的方式。

以下是我的SpringSecurity 配置:

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter 

    private static final String[] AUTH_WHITELIST = 
            // -- swagger ui
            "/",
            "/csrf",
            "/swagger-resources",
            "/swagger-resources/**",
            "/configuration/ui",
            "/configuration/security",
            "/swagger-ui.html",
            "/webjars/**"
    ;

    @Autowired
    @Qualifier("customUserDetailsService")
    private UserDetailsService userDetailsService;

    private final static Integer bCryptEncryptionLevel = 8;

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() 
        return new BCryptPasswordEncoder(bCryptEncryptionLevel);
    

    public SecurityConfig() 
        super();
    

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder authManagerBuilder) throws Exception 
        authManagerBuilder.authenticationProvider(authenticationProvider());
        authManagerBuilder.userDetailsService(userDetailsService)
                .passwordEncoder(bCryptPasswordEncoder());
    

    @Bean
    public DaoAuthenticationProvider authenticationProvider() 
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
        return authenticationProvider;
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable()
                .authorizeRequests()
                    .antMatchers(AUTH_WHITELIST).permitAll()
                    // allow default swagger docket
                    .regexMatchers("\\A/v2/api-docs\\Z").permitAll()
                    // require auth for any other swagger docket
                    .regexMatchers("\\A/v2/api-docs?.*\\Z").authenticated()
                    .antMatchers("/**").authenticated()
                .and()
                .httpBasic()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    

总而言之,我如何将UserServiceDetails 模拟成SpringSecurity 配置,以便我可以在我的Spring Boot 应用程序中对控制器进行单元测试?

【问题讨论】:

【参考方案1】:

我认为你应该使用@Profile,UserDetailesService 是一个接口,它创建了UserDetailesService 的两个实现,一个用于测试,另一个用于其余情况

@Component
@Profile("test")
public class UserDetailesServiceTestImpl implements UserDetailesService




@Component
@Profile("!test")
public class UserDetailesServiceImpl implements UserDetailesService



【讨论】:

问题不是如何模拟特定的类,而是如何模拟并将其注入Bean,以便我可以通过测试向控制器进行身份验证? 根据你的解释修改了答案 这是我想到的。测试时如何将UserDetailesServiceTestImpl 替换为SpringSecurtiy?这是我无法通过的思维障碍。 这正是配置文件将根据活动配置文件帮助您的地方,这将在单元测试期间进行测试 为实现命名“customUserDetailsS​​ervice”,spring 将根据活动配置文件自行选择

以上是关于如何在 Spring Security Bean 中模拟自定义 UserService 详细信息以进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security 循环 bean 依赖

如何使用 Spring Security 3.1.3 和 JSF 创建一个 Bean 来验证我的登录表单

如何使用 Spring Boot Security 修复 Spring Boot Webflux 应用程序中的“名称为 requestMappingHandlerAdapter 的 bean 定义无效

Spring Security:创建 bean 时出错/未定义 bean

Spring Boot,Spring Security,会话范围 Bean 的会话超时问题,@PreDestroy

Spring security DefaultMethodSecurityExpressionHandler bean 未注册 Integration Test 的默认 spring security