【问题标题】:How to eliminate @Configuration classes with security enabled in Spring Boot unit testing如何在 Spring Boot 单元测试中消除启用安全性的 @Configuration 类
【发布时间】:2021-03-05 12:36:00
【问题描述】:

我正在使用一个运行良好的新微服务,并且所有测试用例也运行良好。最近,Spring Boot 微服务启用了带有 sso 的 spring security。微服务运行良好,但测试用例由于安全性而失败。我有一个类需要在春季启动单元测试期间在运行时消除。我在下面提供代码。

@Configuration
@Slf4j
public class CloudSecurityConfig {
    private String host = "some host";
    private String port = System.getenv("redis.port");
    private String password = System.getenv("redis.password");
    private String ssl = System.getenv("redis.ssl");
    
    @Bean
    JedisPoolConfig jedisPoolConfig(@Value("${redis.pool.maxactive}") int maxActive,
            @Value("${redis.pool.maxidle}") int maxIdle, @Value("${redis.pool.minidle}") int minIdle) {
        .... Other code
        return jedisPoolConfig;
    }
    
    @Bean
    JedisConnectionFactory jedisConnectionFactory() throws Exception {
            .... Other code
        
        return jedisConFactory;
    }

    @Bean
    @Primary
    public RedisTemplate<String, CtmUser> redisTemplate() throws Exception {
        .... Other code
        return redisTemplate;
    }
}

我也试过这个链接Java Spring Boot Test: How to exclude java configuration class from test context。但它不起作用。我收到以下错误详细信息。

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<?, ?>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1717) ~[spring-beans-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1273) ~[spring-beans-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227) ~[spring-beans-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    ... 84 common frames omitted

以上内容来自CloudSecurityConfig类。我认为,如果我能够删除此配置,一切都会正常工作。

上面的错误后面跟着下面的错误:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customAuthenticationProvider': Unsatisfied dependency expressed through field 'template'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<?, ?>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

我尝试了以下选项。

//@EnableMongoRepositories
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration()
@SpringBootTest(classes = { ValidationApplication.class, TestMongoConfiguration.class })
//@ImportAutoConfiguration(classes = {ValidationApplication.class,TestMongoConfiguration.class})
//@EnableAutoConfiguration(exclude={ DataSourceAutoConfiguration.class, RedisAutoConfiguration.class,
//        RedisRepositoriesAutoConfiguration.class, MongoAutoConfiguration.class })

//@EnableAutoConfiguration(exclude={ DataSourceAutoConfiguration.class, RedisAutoConfiguration.class,
//      RedisRepositoriesAutoConfiguration.class, MongoAutoConfiguration.class, SecurityAutoConfiguration.class })

//@EnableAutoConfiguration(exclude={ CloudSecurityConfig.class })

//@TestPropertySource(inheritProperties = false, properties = 
//        "spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration")
//@TestConfiguration()
//@ConditionalOnProperty(name = "test", havingValue="test")
@ActiveProfiles("test")
@ComponentScan(basePackages = {"com.a.b.c.d"}
, excludeFilters = {
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {SecurityCloudConfig.class})})
public class CheckTest {

    @Autowired
    private MyController controller;
    
    @Test
    void testAllBeforeEntry() {
        ResponseEntity<?> re = controller.getValdiations();
        boolean flag = re.getStatusCode().is2xxSuccessful();
        assertEquals(true, flag);
    }

}

【问题讨论】:

    标签: java spring spring-boot junit4


    【解决方案1】:

    与其忽略,不如重写配置类。您可以为测试环境编写适当的 TestConfiguration 类。此处添加示例:

    
    @TestConfiguration
    public class TestSecurityConfig {
    
        @Bean
        @Primary
        JedisPoolConfig jedisPoolConfig(@Value("${redis.pool.maxactive}") int maxActive,
                @Value("${redis.pool.maxidle}") int maxIdle, @Value("${redis.pool.minidle}") int minIdle) {
              // your test environment specific code/configuration.
        }
    
        @Bean
        JedisConnectionFactory jedisConnectionFactory() throws Exception {
                .... Other code
            // test environment specific code.
        }
        // .... Other configurations which needs to be override.
    
        
    

    注意:不要忘记在测试 Beans 中添加 @Primary,在测试 application.properties 文件中添加 spring.main.allow-bean-definition-overriding=true。 并在主单元测试类中添加@SpringBootTest(classes = TestSecurityConfig.class) 覆盖原来的Beans。

    您也可以提供 MockBean 而不是真正的。

    【讨论】:

    • 即使我这样做了,它仍然会抛出这个错误Error creating bean with name 'customAuthenticationProvider',因为这需要所有必需的 Redis 连接。
    • 你真的需要真正的customAuthenticationProvider吗?嘲笑那个班级会奏效吗?我在这里看不到任何 customAuthenticationProvider 类..
    • customAuthenticationProvider 位于需要此 Redis 连接的库中。但是在单元测试的情况下,它不是必需的,所以我想在运行时删除这个配置以使其工作。
    • 如果你模拟这个 bean 最好。否则,您可以在名为 customAuthenticationProvider 的 testConfiguration 类中定义另一个 bean。
    猜你喜欢
    • 1970-01-01
    • 2019-03-30
    • 2016-10-15
    • 2015-09-19
    • 2017-12-27
    • 1970-01-01
    • 2016-12-05
    • 2016-01-02
    相关资源
    最近更新 更多