Reputation: 8487
There is a mongo dao class com.foo.bar.dao.CompanyRecommendationDao
and there is a corresponding test class:com.foo.bar.dao.CompanyRecommendationDaoTest
.
@RunWith(SpringRunner.class)
@DataMongoTest(includeFilters = @ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE,value={CompanyRecommendationDao.class}))
@Import(SpringMongoConfig.class)
public class CompanyRecommendationDaoTest
At first run the test class is's ok, but if adding the ComponentScan
annotation above the Application class
@SpringBootApplication
@ComponentScan("com.foo")
public class BarApplication
in this case when run CompanyRecommendationDaoTest could get below error
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'companyManagementService': Unsatisfied dependency expressed through field 'companyMapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'companyMapper' defined in file [/Users/zhugw/develop/workspace/bar/target/classes/com/foo/bar/mapper/CompanyMapper.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
So why it could load other service class, should it only load mongo related class?
From DataMongoTest
javadoc
Can be used when a test focuses only on MongoDB components. Using this annotation will disable full auto-configuration and instead apply only configuration relevant to MongoDB tests.
What is the difference if add @ComponentScan("com.foo") explicitly(default package is com.foo.bar)?
PS. When enable trace log
Situation 1(without @ComponnetScan)
2019-06-02 22:28:08.876 TRACE 13875 --- [ main] o.s.c.a.ClassPathBeanDefinitionScanner : Scanning file [/Users/zhugw/develop/workspace/foo/bar/target/classes/com/foo/bar/dao/CompanyRecommendationDao.class]
2019-06-02 22:28:08.877 TRACE 13875 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.test.context.filter.TestTypeExcludeFilter'
2019-06-02 22:28:08.877 TRACE 13875 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.test.autoconfigure.filter.TypeExcludeFilters'
2019-06-02 22:28:08.877 DEBUG 13875 --- [ main] o.s.c.a.ClassPathBeanDefinitionScanner : Identified candidate component class: file [/Users/zhugw/develop/workspace/foo/bar/target/classes/com/foo/bar/dao/CompanyRecommendationDao.class]
Situation 2(with @ComponnetScan)
2019-06-02 22:40:23.989 TRACE 14573 --- [ main] o.s.c.a.ClassPathBeanDefinitionScanner : Scanning file [/Users/zhugw/develop/workspace/foo/bar/target/classes/com/foo/bar/dao/CompanyRecommendationDao.class]
2019-06-02 22:40:23.989 DEBUG 14573 --- [ main] o.s.c.a.ClassPathBeanDefinitionScanner : Identified candidate component class: file [/Users/zhugw/develop/workspace/foo/bar/target/classes/com/foo/bar/dao/CompanyRecommendationDao.class]
Upvotes: 2
Views: 2482
Reputation: 8487
Reason:
The underlying component scan configuration of @SpringBootApplication defines exclude filters that are used to make sure slicing works as expected. If you are using an explicit @ComponentScan directive on your @SpringBootApplication-annotated class, be aware that those filters will be disabled. If you are using slicing, you should define them again.
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
Resolve:
@ComponentScan(value="com.foo",excludeFilters = { @ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class) })
If you directly use @ComponentScan (that is, not through @SpringBootApplication) you need to register the TypeExcludeFilter with it. See the Javadoc for details.
CompanyRecommendationDaoTest
) @SpringBootApplication
public class DaoTestApplication {
public static void main(String[] args) {
SpringApplication.run(DaoTestApplication.class, args);
}
}
Upvotes: 1
Reputation: 6216
The issue that you are facing might be due to @ComponentScan
. Initially when you use the @DataMongotTest
annotation only spring configures the beans that are necessary for running the mongo only.But when you add the component scan annotation to the main class and set the package scan level like "com.foo"
spring will automatically search and find beans for registration in all packages under this path.
Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
Since you are not essentially providing the entire application data including property values etc when you are running test , spring fails to create the bean for sqlSessionTemplate.java
, which might be needing some property values which are not loaded in test.
Annotation that can be used in combination with @RunWith(SpringRunner.class) for a typical MongoDB test. Can be used when a test focuses only on MongoDB components. Using this annotation will disable full auto-configuration and instead apply only configuration relevant to MongoDB tests. By default, tests annotated with @DataMongoTest will use an embedded in-memory MongoDB process (if available).
It is a good practice to have a separate main class defined for running tests so that you can have full control over the configurations while running tests.
Refer here
Upvotes: 2