In my Spring boot 2.1 project I have different @Configurations for different test (ConfigurationA and ConfigurationB), that reside in different packages. Both configurations define the same set of beans but in a different manner (mocked vs. the real thing)
As I am aware of the Bean overriding mechanism introduced in Spring Boot 2.1, I have set the property: spring.main.allow-bean-definition-overriding=true.
However I do have a test with the following the setup of the following configuration and test class. First there is a @Configuration in the productive part (I'm using Maven):
package com.stackoverflow;
@Configuration
public class ProdConfiguration{
...
}
Then in the test branch there is a general Test @Configuration on the same package level:
package com.stackoverflow
@Configuration
public class TestConfiguration {
@Bean
public GameMap gameMap() {
return Mockito.mock(GameMap.class);
}
}
And in a subpackage I have another @Configuration:
package com.stackoverflow.impl;
@Configuration
public class RealMapTestConfiguration {
@Bean
public GameMap gameMap() {
return new GameMap("testMap.json");
}
}
And then of course there is the test that is troubling me:
package com.stackoverflow.impl;
@ExtendWith(SpringExtension.class)
@SpringBootTest
@ContextConfiguration(classes={RealMapTestConfiguration.class, ProdConfiguration.class})
@ActiveProfiles("bug") // spring.main.allow-bean-definition-overriding=true
public class MapImageServiceIT {
@Autowired
private GameMap map;
}
It turns out that the injected GameMap into my test is a mock instance from TestConfiguration instead of the real thing from RealMapTestConfiguration. Aparrently in my test I have the configuration from ProdConfiguration and TestConfiguration, when I wanted ProdConfiguration and RealMapTestConfiguration. As the beans defined in the ProdConfiguration and *TestConfiguration are different the combination works, but TestConfiguration and RealMapTestConfiguration define the same been. It seems like the TestConfiguration is picked up by component scanning as it is in the same package as ProdConfiguration.
I was under the impression that when overriding beans the bean definition that is closer to the test class would be preferred. However this seems not to be the case.
So here are my questions:
- When overriding beans, what is the order? Which bean overrides which one?
- How to go about to get the correct instance in my test (using a different bean name is not an option, as in reality the injected bean is not directly used in the test but in a service the test uses and there is no qualifier on it.)
@MockBeanin your test class?MockBeansolved the issues, as I could then define the mocked behaviour in the setup and only use oneTestConfiguration.