Annotation Interface ComponentScanExcludingConfigurationForTest
@ConfigurationForTest
annotation instead of the standard @Configuration
annotation. This is meant as a solution for a rather common problem that arises when your application
uses @ComponentScan to find @Services, @Components etc, and have integration tests that reside in "src/test/java",
but has the same package as the application code (to allow for package access). In the tests, you might want to
include the entire application's Spring configuration, thus you include the same @ComponentScan. The problem now is
that since all the test classes are included on the classpath when running a test, and at the same time reside in the
same package structure, the component scan will pick up all tests' @Configuration classes too. This is absolutely not
what you wanted - in particular if e.g. two different tests tries to set up two different variants of a mock
collaborating Mats endpoint (that is, an application-external service that this application communicates with):
You'll end up trying to take up both variants at the same time, and since they have the same endpointId, Mats will
refuse this.
If you employ this annotation (@ComponentScanExcludingConfigurationForTest) - or set up the same "excludeFilters" as
this annotation does - you will not include any configuration classes that are annotated with
@ConfigurationForTest
instead of the ordinary @Configuration. However, each test will
still pick up its own inner static @ConfigurationForTest class(es).
A test class employing @ConfigurationForTest would look something like this:
@MatsTestProfile // <- If you employ the JmsSpringConnectionFactoryProducer's logic to handle JMS ConnectionFactory @RunWith(SpringRunner.class) public class IntegrationTestClass { @ConfigurationForTest @Import(ApplicationSpringConfigurationClass_Using_ComponentScanExcludingConfigurationForTest.class) public static class InnerStaticConfigurationClassForTest { // @Bean definitions // @MatsMapping definitions } // @Inject'ed fields.. // @Test-methods.. }
If you want to do the exclusion on your own, you can use the standard @ComponentScan, making sure you include this excludeFilters property:
@ComponentScan(excludeFilters = { @Filter(type = FilterType.ANNOTATION, value = ConfigurationForTest.class) })
This class has @AliasFor all properties that Spring 4.x has on @ComponentScan. If new properties arrive later which you want to use, you will have to do the exclusion on your own.
NOTICE: An alternative way to achieve the same effect is to annotate the integration test class with @ContextConfiguration, pointing to both the application's Spring setup, and also the configuration class residing within the test class - but where the test's configuration class is not annotated with @Configuration. Such an integration test class would look something like this:
@MatsTestProfile // <- If you employ the JmsSpringConnectionFactoryProducer's logic to handle JMS ConnectionFactory @RunWith(SpringRunner.class) @ContextConfiguration(classes = { ApplicationSpringConfigurationClass_Using_ComponentScan.class, InnerStaticConfigurationClassForTest.class }) public class IntegrationTestClass { // Notice how this configuration class is NOT annotated with @Configuration, to avoid being picked up by // application's @ComponentScan public static class InnerStaticConfigurationClassForTest { // @Bean definitions // @MatsMapping definitions } // @Inject'ed fields.. // @Test-methods.. }
-
Optional Element Summary
Optional ElementsModifier and TypeOptional ElementDescriptionClass<?>[]
Type-safe alternative tobasePackages()
for specifying the packages to scan for annotated components.String[]
Base packages to scan for annotated components.org.springframework.context.annotation.ComponentScan.Filter[]
Specifies which types are not eligible for component scanning.org.springframework.context.annotation.ComponentScan.Filter[]
Specifies which types are eligible for component scanning.boolean
Specify whether scanned beans should be registered for lazy initialization.Class<? extends org.springframework.beans.factory.support.BeanNameGenerator>
TheBeanNameGenerator
class to be used for naming detected components within the Spring container.Controls the class files eligible for component detection.org.springframework.context.annotation.ScopedProxyMode
Indicates whether proxies should be generated for detected components, which may be necessary when using scopes in a proxy-style fashion.Class<? extends org.springframework.context.annotation.ScopeMetadataResolver>
TheScopeMetadataResolver
to be used for resolving the scope of detected components.boolean
Indicates whether automatic detection of classes annotated with@Component
@Repository
,@Service
, or@Controller
should be enabled.String[]
Alias forbasePackages()
.
-
Element Details
-
value
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="value") String[] valueAlias forbasePackages()
.Allows for more concise annotation declarations if no other attributes are needed — for example,
@ComponentScan("org.my.pkg")
instead of@ComponentScan(basePackages = "org.my.pkg")
.- Default:
- {}
-
basePackages
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="basePackages") String[] basePackagesBase packages to scan for annotated components.value()
is an alias for (and mutually exclusive with) this attribute.Use
basePackageClasses()
for a type-safe alternative to String-based package names.- Default:
- {}
-
basePackageClasses
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="basePackageClasses") Class<?>[] basePackageClassesType-safe alternative tobasePackages()
for specifying the packages to scan for annotated components. The package of each class specified will be scanned.Consider creating a special no-op marker class or interface in each package that serves no purpose other than being referenced by this attribute.
- Default:
- {}
-
nameGenerator
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="nameGenerator") Class<? extends org.springframework.beans.factory.support.BeanNameGenerator> nameGeneratorTheBeanNameGenerator
class to be used for naming detected components within the Spring container.The default value of the
BeanNameGenerator
interface itself indicates that the scanner used to process this@ComponentScan
annotation should use its inherited bean name generator, e.g. the defaultAnnotationBeanNameGenerator
or any custom instance supplied to the application context at bootstrap time.- See Also:
-
AnnotationConfigApplicationContext.setBeanNameGenerator(BeanNameGenerator)
- Default:
- org.springframework.beans.factory.support.BeanNameGenerator.class
-
scopeResolver
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="scopeResolver") Class<? extends org.springframework.context.annotation.ScopeMetadataResolver> scopeResolverTheScopeMetadataResolver
to be used for resolving the scope of detected components.- Default:
- org.springframework.context.annotation.AnnotationScopeMetadataResolver.class
-
scopedProxy
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="scopedProxy") org.springframework.context.annotation.ScopedProxyMode scopedProxyIndicates whether proxies should be generated for detected components, which may be necessary when using scopes in a proxy-style fashion.The default is defer to the default behavior of the component scanner used to execute the actual scan.
Note that setting this attribute overrides any value set for
scopeResolver()
.- See Also:
-
ClassPathBeanDefinitionScanner.setScopedProxyMode(ScopedProxyMode)
- Default:
- DEFAULT
-
resourcePattern
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="resourcePattern") String resourcePatternControls the class files eligible for component detection.Consider use of
includeFilters()
andexcludeFilters()
for a more flexible approach.- Default:
- "**/*.class"
-
useDefaultFilters
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="useDefaultFilters") boolean useDefaultFiltersIndicates whether automatic detection of classes annotated with@Component
@Repository
,@Service
, or@Controller
should be enabled.- Default:
- true
-
includeFilters
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="includeFilters") org.springframework.context.annotation.ComponentScan.Filter[] includeFiltersSpecifies which types are eligible for component scanning.Further narrows the set of candidate components from everything in
basePackages()
to everything in the base packages that matches the given filter or filters.Note that these filters will be applied in addition to the default filters, if specified. Any type under the specified base packages which matches a given filter will be included, even if it does not match the default filters (i.e. is not annotated with
@Component
).- See Also:
- Default:
- {}
-
excludeFilters
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="excludeFilters") org.springframework.context.annotation.ComponentScan.Filter[] excludeFiltersSpecifies which types are not eligible for component scanning. NOTICE: For this special variant, the default is set to exclude @ConfigurationForTest annotated classes- See Also:
- Default:
- {@org.springframework.context.annotation.ComponentScan.Filter(type=ANNOTATION, value={io.mats3.spring.ConfigurationForTest.class})}
-
lazyInit
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="lazyInit") boolean lazyInitSpecify whether scanned beans should be registered for lazy initialization.Default is
false
; switch this totrue
when desired.- Since:
- 4.1
- Default:
- false
-