When writing tests, it is possible to make static inner classes annotated with Configuration, and have them automatically picked up.
However, if you both have the same package structure for your tests as the app, and employ classpath scanning in the app, if you now point your ContextConfiguration to a app Configuration that specify classpath scanning, these inner classes will also be picked up by the classpath scanning. This is unfortunate when you have multiple such tests in the same package, as all of them then will be picked up, not only the one for the current test.
Suggestion: Make a specific @ConfigurationForTest that will automatically be picked up by the test, but not by the classpath scanning. And these should be picked up even if you specify a specific set of classes in the ContextConfiguration annotation, see comment in parenthesis in #26142..
Comment From: sbrannen
The proposed @ConfigurationForTest
sounds identical to Spring Boot's @TestConfiguration
support.
Are you using Spring Boot and its testing support?
Comment From: stolsvik
No, not using Spring Boot, didn't know about that feature. Can you port it back to standard Spring?
Actually, I find it a bit sad that new cool features are just being released in Spring Boot, and not in "Spring Proper". Same with @ConditionalOnMissingBean
and stuff like this.
From the TestConfiguration
link you gave, I end up on the TypeExcludeFilter
, and that is actually what I have implemented with a ComponentScan
replacement - needless to say, it would have been awesome if such filtering out of the TestConfiguration
/ConfigurationForTest
was simply included in the default ComponentScan
:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Configuration
// meta-annotation:
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.ANNOTATION, value = ConfigurationForTest.class)
})
public @interface ComponentScanExcludingConfigurationForTest {
/**
* Alias for {@link #basePackages}.
* <p>
* Allows for more concise annotation declarations if no other attributes are needed — for example,
* {@code @ComponentScan("org.my.pkg")} instead of {@code @ComponentScan(basePackages = "org.my.pkg")}.
*/
@AliasFor(annotation = ComponentScan.class, attribute = "value")
String[] value() default {};
/**
* Base packages to scan for annotated components.
* <p>
* {@link #value} is an alias for (and mutually exclusive with) this attribute.
* <p>
* Use {@link #basePackageClasses} for a type-safe alternative to String-based package names.
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] basePackages() default {};
...
...
Comment From: snicoll
Actually, I find it a bit sad that new cool features are just being released in Spring Boot, and not in "Spring Proper". Same with @ConditionalOnMissingBean and stuff like this.
This is far from being as easy as it may sound. Conditions like this rely on the fact that configuration is processed in a given order that Spring Boot guarantees and that a custom usage of the core framework couldn't. By adding the feature in the core framework, we'd be putting ourselves in a weird situation where the feature as documented would work "if". You can see that ConditionalOnMissingBean should be used on auto-configurations only. And moving that to the core framework would induce a lot of work that would prevent us to work on new features.
It's the same for this feature, we can't bake a default like that in component scan as it simply doesn't know about the TCF. Spring Boot can do all those things because there's a concept of an application and it sits on top of the framework pieces.
It would be possible for you to use Spring Boot without the features that you don't need/can't use/don't like. The testing bit is one of those.