首页 > 解决方案 > 为什么 @ComponentScan 然后 DataMongoTest 不起作用

问题描述

有一个 mongo dao 类com.foo.bar.dao.CompanyRecommendationDao,也有一个对应的测试类: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

第一次运行测试类是可以的,但是如果ComponentScan在Application类上面添加注释

@SpringBootApplication
@ComponentScan("com.foo")
public class BarApplication 

在这种情况下,运行 CompanyRecommendationDaoTest 可能会出现以下错误

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

那么为什么它可以加载其他服务类,它应该只加载 mongo 相关类?

来自DataMongoTestjavadoc

当测试只关注 MongoDB 组件时可以使用。使用此注解将禁用完全自动配置,而是仅应用与 MongoDB 测试相关的配置。

如果显式添加 @ComponentScan("com.foo") 有什么区别(默认包是 com.foo.bar)?

PS。启用跟踪日志时

情况1(没有@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]

情况2(使用@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]

标签: spring-bootspring-data-mongodbspring-test

解决方案


您面临的问题可能是由于@ComponentScan. 最初,当您使用@DataMongotTest注解时,spring 仅配置运行 mongo 所必需的 bean。但是当您将组件扫描注解添加到主类并设置包扫描级别时, "com.foo"spring 将自动搜索并查找所有注册的 bean此路径下的软件包。

Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required

由于您在运行 test 时实际上并未提供包括属性值等在内的整个应用程序数据,因此 spring 无法为 bean 创建 bean sqlSessionTemplate.java,这可能需要一些未在 test 中加载的属性值。

可以与 @RunWith(SpringRunner.class) 结合使用的注释,用于典型的 MongoDB 测试。当测试只关注 MongoDB 组件时可以使用。使用此注解将禁用完全自动配置,而是仅应用与 MongoDB 测试相关的配置。默认情况下,使用 @DataMongoTest 注释的测试将使用嵌入式内存中的 MongoDB 进程(如果可用)。

为运行测试定义一个单独的主类是一种很好的做法,这样您就可以在运行测试时完全控制配置。

参考这里


推荐阅读