Spring Boot在单元测试时删除@Component

Posted

技术标签:

【中文标题】Spring Boot在单元测试时删除@Component【英文标题】:Spring Boot remove @Component when unit testing 【发布时间】:2017-01-17 19:53:00 【问题描述】:

请耐心等待,因为这是我第一次使用 Spring Boot,所以这只是我认为正在发生的事情......

我有几个用@Scheduled 注释的方法。它们工作得很好,我已经配置并注入了所有依赖项。这些依赖关系很重,依赖于互联网连接等。我将它们注释为@Lazy,所以它们只在最后一分钟被实例化。

但是,包含预定方法的类需要用@Component 标记,这意味着它们是在启动时创建的。这引发了连锁反应,无论我当前运行的测试是否真的需要它们,都会产生我所有的依赖关系。

当我在 CI 服务器上运行单元测试时,它们会失败,因为服务器没有通过数据库进行身份验证(也不应该)。

测试这些@Scheduled 作业的测试注入了它们自己的模拟,因此它们工作正常。但是,由于仍在创建类,因此完全不相关的测试会导致问题。我显然不想在这些测试中为完全不相关的类创建模拟。

如何防止在测试运行时创建某个 @Component

预定作业类:

package example.scheduledtasks;

@Component
public class ScheduledJob 

    private Database database;

    @Autowired
    public AccountsImporter(Database database) 
        this.database = database;
    

    @Scheduled(cron="0 0 04 * * *")
    public void run() 
        // Do something with the database
    

配置类:

package example

@Configuration
public class ApplicationConfig 

    @Bean
    @Lazy
    public Database database() 
        return ...;// Some heavy operation I don't want to do while testing.
    

【问题讨论】:

也许this answer 可能会有所帮助。 感谢@Jaims,我已经看到了条件注释,但无法弄清楚我的条件是什么。有什么想法吗? 一种常见的方法是使用不同的配置文件。您有一个带有 @Profile() 注释的 TestConfig 类,它可以将您的数据库模拟为一个轻量级对象。然后在您的测试类中,您可以使用@ActiveProfiles() 来选择您的测试配置。在生产中,您可以提供不同的配置文件。 【参考方案1】:

我知道你说过:

我显然不想在这些测试中为完全不相关的类创建模拟。

不过,正如您所知,您可以轻松地为这个测试覆盖不需要的组件:

@RunWith(...)
@Context...
public class YourTest 
    public static class TestConfiguration 
        @Bean
        @Primary
        public Database unwantedComponent()
            return Mockito.mock(Database.class);
        
    

    @Test
    public void yourTest()
        ...
    

类似的问题/答案:Override a single @Configuration class on every spring boot @Test

【讨论】:

谢谢亚历克斯。虽然这解决了测试不通过的直接问题,但我仍然认为 Spring 在运行测试时注册计划任务没有意义。测试应该只是我实例化的类,当然?! 这不会从上下文中删除另一个 bean。如果要替换 bean,则需要确保 bean 的名称在测试配置中与通常在 spring 上下文中的名称相同。此答案仅在您尝试将新值注入单值依赖项时才有帮助。【参考方案2】:

只需将以下内容添加到您的测试类中:

@MockBean
public Database d;

【讨论】:

这太巧妙了!在 Spock 中使用 @SpringBean Database d = Mock()

以上是关于Spring Boot在单元测试时删除@Component的主要内容,如果未能解决你的问题,请参考以下文章

spring boot单元测试spring context重复加载问题

Spring Boot maven 多模块项目——单元测试(应用上下文)

Spring Boot APP - 单元测试[重复]

指定端口时,Spring Boot Actuator 端点的单元测试不起作用

怎样使用Spring Boot项目的单元测试?

Spring Boot 不运行单元测试