对特定于 Spring 引导测试的 @TestConfiguration 感到困惑

Posted

技术标签:

【中文标题】对特定于 Spring 引导测试的 @TestConfiguration 感到困惑【英文标题】:Confused about Spring boot test specific @TestConfiguration 【发布时间】:2018-07-07 02:36:27 【问题描述】:

根据Spring Boot Docs,嵌套的@TestConfiguration 应该被测试自动检测到。

但是在我的测试代码中,当我运行整个测试类时出现问题,即使我通过@Import 明确添加它也没有检测到。测试代码结构如下:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
//@Import(IntegrationTests.TestSecurityConfig.class)
public class IntegrationTests 

// test methods

   // test configuration
   @TestConfiguration
   static class TestSecurityConfig 


当我单独运行单个测试用例(测试方法)时,所有测试都按预期通过,但是当我直接运行测试类时,一些测试失败,@TestConfiguration 未应用测试。

这个IntegrationTests的完整代码是here。

更新: 在我的代码中添加了一种解决方法以使测试通过。

@TestComponent
@Slf4j
static class TestUserDetailsService implements UserDetailsService 

    private final PasswordEncoder passwordEncoder;

    TestUserDetailsService(PasswordEncoder passwordEncoder) 
        this.passwordEncoder = passwordEncoder;
    

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
        UserDetails user = User.withUsername("user")
            .password(passwordEncoder.encode("password"))
            .roles("USER")
            .accountExpired(false)
            .accountLocked(false)
            .credentialsExpired(false)
            .disabled(false)
            .build();

        UserDetails admin = User.withUsername("admin")
            .password(passwordEncoder.encode("password"))
            .roles("ADMIN")
            .accountExpired(false)
            .accountLocked(false)
            .credentialsExpired(false)
            .disabled(false)
            .build();

        log.debug("dummy user:" + user);
        log.debug("dummy admin:" + admin);


        if ("user".equals(username)) 
            return user;
         else 
            return admin;
        
    


@TestConfiguration
@Slf4j
@Import(TestUserDetailsService.class)
@Order(-1)
static class TestSecurityConfig extends WebSecurityConfigurerAdapter 

    @Inject
    PasswordEncoder passwordEncoder;

    @Inject
    UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
            .httpBasic()
            .and()
            .authorizeRequests()
            .antMatchers(HttpMethod.GET, "/posts/**").permitAll()
            .antMatchers(HttpMethod.DELETE, "/posts/**").hasRole("ADMIN")
            .anyRequest().authenticated()
            .and()
            .csrf().disable();
    

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

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


还有一些事情让我感到困惑。

    在测试类中,为什么@TestConfiguration无法检测到位于同一个测试中的@TestComponent,我必须添加@Import来修复它。 正如security section of Spring Boot Docs 中所述,我认为定义一个UserDetailsService bean 就足够了,它将为用户提供安全服务,但它在测试中不起作用。我必须配置一个WebSecurityConfigurerAdapter 并暴露AuthenticationManager 进行测试,为什么?更让我困惑的是,如前所述,如果没有为测试定义WebSecurityConfigurerAdapter,则可以一一运行测试。 注释WebSecurityConfigurerAdapter@TestConfiguration没有得到更高的顺序,我必须在上面添加@Order。我在想@TestConfiguration bean 应该自动获取 Primary 并替换我的应用程序配置中的 bean,对吗?

【问题讨论】:

如果您将 Config 类放在测试类之外,它应该可以工作。有什么理由让你在一堂课上需要这一切? @Dovmo 试图退出测试类,得到了相同的结果。 @Dovmo 这可能是加载 SpringSecuirty 的应用程序上下文时的特定问题,在another test、TestConfiguration 工作。 @TestConfiguration 申请迟到时出现问题。到那时,另一个带有@ConditionalOnBean 的组件已经被跳过。使用 @Order(Ordered.HIGHEST_PRECEDENCE) 有帮助。 @leonid @Order(Ordered.HIGHEST_PRECEDENCE) 在我的@ConditionalOnBean 处理之后完美解决了我的@TestConfiguration 问题。 【参考方案1】:

在我的情况下,只需添加 @Order(Ordered.HIGHEST_PRECEDENCE) 即可解决:

@Order(Ordered.HIGHEST_PRECEDENCE)
@TestConfiguration

我不太清楚为什么这不是默认设置。我的 @ConditionalOnBean@TestConfiguration 实际初始化这些 bean 之前进行了评估。

【讨论】:

以上是关于对特定于 Spring 引导测试的 @TestConfiguration 感到困惑的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Cloud GCP pubsub 中创建特定于消息通道的线程

AndroidQ兼容性适配指南

AndroidQ兼容性适配指南

AndroidQ兼容性适配指南

HSQL 在 Spring 引导测试中不起作用

html 特定于引导程序,您可以执行以下操作从具有本地回退的CDN加载