I am having a SimpleTest :
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SimpleTestConfig.class)
public class SimpleTest {
@Test
public void test() {
assertThat(true);
}
}
and a configuration for this test :
@SpringBootApplication
@ComponentScan(basePackageClasses = {
SimpleTestConfig.class,
Application.class
},
excludeFilters = @ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = Starter.class))
public class SimpleTestConfig {
}
I am trying to exclude the Starter class
package application.starters;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class Starter {
@PostConstruct
public void init(){
System.out.println("initializing");
}
}
And the Application class looks like this :
package application;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import static org.springframework.boot.SpringApplication.run;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
run(Application.class, args);
}
}
But for a very weird reason the Starter class is still getting initialized.
Can anyone explain why the ComponentScan excludeFilters is not excluding my Starter class ?
16.2 Disabling Specific Auto-configuration Classes If the class is not on the classpath, you can use the excludeName attribute of the annotation and specify the fully qualified name instead. Finally, you can also control the list of auto-configuration classes to exclude by using the spring. autoconfigure.
Actually the @SpringBootApplication annotation is equivalent to using @Configuration , @EnableAutoConfiguration and @ComponentScan with their default attributes.
exclude , not excludes as in the release notes. This helps prevent Spring Boot from loading autoconfig classes in the presence of multiple @EnableAutoConfiguration / @SpringBootApplication annotations.
To disable the default filter, set the useDefaultFilters element of the @ComponentScan annotation to false.
Each component scan does filtering individually. While you exclude Starter.class from SimpleTestConfig, SimpleTestConfig initializes Application, which does it's own @ComponentScan without excluding Starter.
The clean way of using ComponentScan is for each ComponentScan to scan separate packages, that way each filter works fine. When 2 separate ComponentScans scan the same package (as in your tests), this does not work.
One way to trick this is to provide a mock Starter bean:
import org.springframework.boot.test.mock.mockito.MockBean;
public class SimpleTest {
@MockBean
private Starter myTestBean;
...
}
Spring will use that mock instead of the real class, thus the @PostConstruct method will not be called.
Other common solutions:
Application.class in any unit test@Profile("!TEST") on the Starter class@ConditionalOn... annotation on the Starter classIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With