I configure a Clock
bean like this:
@Configuration
public class ClockConfiguration {
@Bean
Clock clock() {
return Clock.systemDefaultZone();
}
}
For an integration test, however, I need a Clock
instance with a fixed time, so I added a static @TestConfiguration
like this:
@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() {}
}
But when running the test, the application context cannot be loaded. Instead, this error message is shown:
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.
My understanding was that the static @TestConfiguration
would actually take care of that?
CodePudding user response:
From Spring boot 2.0 and upwards, you have to enable bean overriding in application.yml to allow Spring to override the instance of Clock
from the actual application with the one in you want in integration test:
spring:
main:
allow-bean-definition-overriding: true
CodePudding user response:
It seems that several workarounds will be available.
1:
Set spring.main.allow-bean-definition-overriding=true
on src/test/resources/application.properties
(or on application-test.properties
; you activate test
profile) .
2:
If @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());
}
}
See also: