Spring集成测试-重写bean的惯用方法
如何以惯用的方式覆盖Spring(Boot)集成测试中的bean 到目前为止,我的源代码配置如下:Spring集成测试-重写bean的惯用方法,spring,spring-boot,spring-boot-test,Spring,Spring Boot,Spring Boot Test,如何以惯用的方式覆盖Spring(Boot)集成测试中的bean 到目前为止,我的源代码配置如下: @Configuration class ApplicationConfiguration { @Bean CarsRepository carsRepository() { // return some real sql db } } @SpringBootTest class ApplicationISpec extends Specification { @Conf
@Configuration
class ApplicationConfiguration {
@Bean
CarsRepository carsRepository() {
// return some real sql db
}
}
@SpringBootTest
class ApplicationISpec extends Specification {
@Configuration
@Import(Application.class)
static class TestConfig {
@Bean
@Primary
CarsRepository testsCarsRepository() {
// return some in-memory repository
}
}
def "it can do stuff with cars"() {
// do some REST requests to application and verify it works
// there is no need to make real calls to real DB
}
}
还有这样的测试:
@Configuration
class ApplicationConfiguration {
@Bean
CarsRepository carsRepository() {
// return some real sql db
}
}
@SpringBootTest
class ApplicationISpec extends Specification {
@Configuration
@Import(Application.class)
static class TestConfig {
@Bean
@Primary
CarsRepository testsCarsRepository() {
// return some in-memory repository
}
}
def "it can do stuff with cars"() {
// do some REST requests to application and verify it works
// there is no need to make real calls to real DB
}
}
首先,testbeantestscarsepository
方法必须不同于原始方法(这并不明显,也没有警告/错误)。
但最后一个问题是:在集成测试中用Spring覆盖bean的惯用方法是什么
当我在上发布关于方法名的WTF时,我说@Primary
不打算用于在测试中重写bean
那么,首选的方法是什么呢?您可以使用
@Profile
和@ActiveProfile
注释来分离测试和生产配置。例如,将测试配置更改为:
@SpringBootTest
@ActiveProfiles("test")
class CarsISpec extends Specification {
@Configuration
@Import(Application.class)
@Profile("test")
static class TestConfig {
@Bean
CarsRepository testsCarsRepository() {
// return some in-memory repository
}
}
}
别忘了用@Profile(“!test”)
标记生产配置应用程序配置
此外,Spring Boot还提供了大量的测试工具(例如带有嵌入式数据库的
@DataJpaTest
,用于在上下文中模拟bean的@MockBean
),等等)@MockBean
看起来是一个不错的选择。@StephaneNicoll我编辑了这篇文章,所以它介绍了更多的用例。我不想嘲笑我的豆子。与此相反,我只想用其他一些只用于测试的实现来替换它。假设我想运行Spring集成测试(这样所有的bean图都被加载),但我想用内存实现替换一些边界bean(如DB、外部服务或其他),这就是为什么我们创建了MockBean
。如果您想使用内存数据库运行,我们也支持它(@AutoconfigureTestDatabase
)。在不使用概要文件的情况下重写bean需要排序并使用相同的bean名称,因此有点脆弱。所以在拒绝之前我会先看看这些选项。@StephaneNicoll谢谢你的意见。所以对我来说,@Profile
&@Primary
可能是一条出路。我想用测试bean替换应用程序bean。它不必与数据库相关。它可以有一些配置选项,或者类似的东西。我不想嘲笑它。我只想对测试使用不同的实现。谢谢你的贡献!您不需要@Primary
。被接受的答案在我看来有点好,我知道这种方法,但在我的推特上与Stepahne Nicoll的答案相混淆,所以这就是我问的原因。尽管如此,还是要感谢您的投入!顺便说一句,你不需要所有的代码。如果你的TestConfig
只有@TestConfiguration
,它就可以工作了。ActiveProfiles将禁用“生产”服务,并在默认行为的顶部应用额外的配置(基本上检测应用程序
类)。如果您同意,您可以编辑您的答案吗?谢谢您的回复!老实说,我不明白如何正确地将@TestConfiguration
应用于这段代码。我能请你把你自己的答案和你的方法贴在一起吗?包括@ActiveProfiles
不是最佳选择的原因。我相信这会对我和问题的作者有所帮助。提前谢谢!这种方法的关键弱点是需要将@Profile(“!test”)
添加到应用程序bean中。我希望我的测试有选择地逐个替换任何应用程序bean,而不是在同一测试中同时替换所有应用程序bean。。。使用这种方法是不可能的,因为只要我将@Profile(“!test”)
添加到我的bean中,我的所有测试都将需要另一个“mock bean”而不是这个bean,并且在我提供bean的一些实现之前应用程序上下文将不会启动(因为其他应用程序的bean可以依赖它)。