BeanDefinitionOverrideException 为集成测试提供 bean / @SpringBootTest
BeanDefinitionOverrideException when supplying bean for integration test / @SpringBootTest
我这样配置 Clock
bean:
@Configuration
public class ClockConfiguration {
@Bean
Clock clock() {
return Clock.systemDefaultZone();
}
}
但是,对于集成测试,我需要一个具有固定时间的 Clock
实例,所以我添加了一个静态 @TestConfiguration
,如下所示:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(initializers = WireMockInitializer.class)
@AutoConfigureWebTestClient
@ActiveProfiles("test")
class MyIT {
@TestConfiguration
static class ClockTestConfiguration {
@Bean
public Clock clock() {
return Clock.fixed(Instant.ofEpochMilli(1635513004000L), ZoneId.systemDefault());
}
}
@Autowired
WireMockServer wireMockServer;
@Autowired
private WebTestClient webTestClient;
@AfterEach
void afterEach() {
wireMockServer.resetAll();
}
@Test
void testFoo() {}
}
但是运行测试时,无法加载应用上下文。相反,显示此错误消息:
org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'clock' defined in de.myapp.MyIT$ClockTestConfiguration
There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=clockConfiguration; factoryMethodName=clock; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [de/myapp/ClockConfiguration.class]] bound.
我的理解是静态 @TestConfiguration
实际上会解决这个问题?
从 Spring boot 2.0 及更高版本开始,您必须在 application.yml 中启用 bean 覆盖,以允许 Spring 从实际应用程序中覆盖 Clock
的实例在集成测试中你想要的那个:
spring:
main:
allow-bean-definition-overriding: true
似乎有几种解决方法。
1:
在 src/test/resources/application.properties
上设置 spring.main.allow-bean-definition-overriding=true
(或在 application-test.properties
上;您激活 test
配置文件)。
2:
如果@Qualifier
is not specified on auto-wiring, define test bean as @Primary
with different bean name:
@TestConfiguration
static class ClockTestConfiguration {
@Bean("fixedClock")
@Primary
public Clock clock() {
return Clock.fixed(Instant.ofEpochMilli(1635513004000L), ZoneId.systemDefault());
}
}
另请参阅:
我这样配置 Clock
bean:
@Configuration
public class ClockConfiguration {
@Bean
Clock clock() {
return Clock.systemDefaultZone();
}
}
但是,对于集成测试,我需要一个具有固定时间的 Clock
实例,所以我添加了一个静态 @TestConfiguration
,如下所示:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(initializers = WireMockInitializer.class)
@AutoConfigureWebTestClient
@ActiveProfiles("test")
class MyIT {
@TestConfiguration
static class ClockTestConfiguration {
@Bean
public Clock clock() {
return Clock.fixed(Instant.ofEpochMilli(1635513004000L), ZoneId.systemDefault());
}
}
@Autowired
WireMockServer wireMockServer;
@Autowired
private WebTestClient webTestClient;
@AfterEach
void afterEach() {
wireMockServer.resetAll();
}
@Test
void testFoo() {}
}
但是运行测试时,无法加载应用上下文。相反,显示此错误消息:
org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'clock' defined in de.myapp.MyIT$ClockTestConfiguration
There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=clockConfiguration; factoryMethodName=clock; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [de/myapp/ClockConfiguration.class]] bound.
我的理解是静态 @TestConfiguration
实际上会解决这个问题?
从 Spring boot 2.0 及更高版本开始,您必须在 application.yml 中启用 bean 覆盖,以允许 Spring 从实际应用程序中覆盖 Clock
的实例在集成测试中你想要的那个:
spring:
main:
allow-bean-definition-overriding: true
似乎有几种解决方法。
1:
在 src/test/resources/application.properties
上设置 spring.main.allow-bean-definition-overriding=true
(或在 application-test.properties
上;您激活 test
配置文件)。
2:
如果@Qualifier
is not specified on auto-wiring, define test bean as @Primary
with different bean name:
@TestConfiguration
static class ClockTestConfiguration {
@Bean("fixedClock")
@Primary
public Clock clock() {
return Clock.fixed(Instant.ofEpochMilli(1635513004000L), ZoneId.systemDefault());
}
}
另请参阅: