-
Notifications
You must be signed in to change notification settings - Fork 41.6k
Description
Summary
Hello Spring. Forgive me if this is better transferred to Spring Framework, but I found an inconsistent behavior with AutoConfiguration ordering in a @SpringBootTest when using @ImportAutoConfiguration so posting it here first.
Consider the case where I have 3 AutoConfigurations where one of the AutoConfigurations wants to run before one, but after another, and one of these AutoConfiguration comes from another spring library.
The library AutoConfiguration
@AutoConfiguration
public class BarAutoConfiguration {
@Bean
public Bar bar() {
return new Bar();
}
}And the other two AutoConfiguration.
@AutoConfiguration(before = AppConfig.class, afterName = "com.example.library.BarAutoConfiguration")
@ConditionalOnClass(Bar.class)
@ConditionalOnBean(Bar.class)
public class FooConfig {
@Bean
public Foo foo(Bar bar) {
return new Foo(bar);
}
}
@AutoConfiguration
public class AppConfig {
@Bean
public ConsumerOfFoo consumerOfFoo(List<Foo> foo) {
return new ConsumerOfFoo(foo);
}
}To aid in testing, I also created a test slice for my library
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@ImportAutoConfiguration
public @interface EnableBarTest {
}Which simply loads com.example.library.BarAutoConfiguration via META-INF/spring/com.example.library.EnableBarTest.imports
I then want to have a a tests that Loads all 3 of these in this manner.
@SpringBootTest(classes = {AppConfig.class, FooConfig.class}, properties = {"debug=true"})
@EnableBarTest // imports BarAutoConfiguration
public class FooConsumerTest {
@MockitoSpyBean
private Bar bar;
@Autowired
ConsumerOfFoo consumerOfFoo;
@Test
public void spanishTest() {
Mockito.when(bar.getGreeting()).thenReturn("Hola");
// test assertions
}
}In this case, BarAutoConfiguration is not ran before FooConfig as directed by afterName = "com.example.library.BarAutoConfiguration" so the conditions of the test breaks as the Foo bean is not created early enough. The specific ordering directives do not seem to be applied as expected.
Expectations
AutoConfiguration ordering would be preserved in @SpringBootTest for imported AutoConfigurations.
Workarounds
I can, of course, move BarAutoConfiguration into classes {} block and config order behaves as expected. I don't want to do that since this comes from an external library which requires the app to understand the code. Instead I want them to simply use my @EnableBarTest test slice which uses the @ImportAutoConfiguration mechanism. This allows me to decouple and change auto-configurations in my library without breaking users.
Reproducer
I dropped a Reproducer of this example here. You can run this test to reproduce the ordering problem.