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 多模块项目——单元测试(应用上下文)