为什么在运行Spring集成测试时没有这种异常
我有一个springboot项目,其中一个开发人员已经针对内存中的DB编写了集成测试。在我提出问题之前,这里有一些背景:为什么在运行Spring集成测试时没有这种异常,spring,integration-testing,context-configuration,Spring,Integration Testing,Context Configuration,我有一个springboot项目,其中一个开发人员已经针对内存中的DB编写了集成测试。在我提出问题之前,这里有一些背景: 我们有以下Maven模块: 1) web持久性:它存储所有实体、接口和相应的实现。所有这些类都在包com.mycompany.persistence中 2) web服务:存储所有rest控制器和spring安全相关类。这些都在包com.mycompany.services 3) web服务模块对web持久性模块具有maven模块依赖性。 4) 在web服务模块中,我们定义了一
我们有以下Maven模块:
1) web持久性:它存储所有实体、接口和相应的实现。所有这些类都在包
com.mycompany.persistence
中2) web服务:存储所有rest控制器和spring安全相关类。这些都在包
com.mycompany.services
3) web服务模块对web持久性模块具有maven模块依赖性。
4) 在web服务模块中,我们定义了一个服务
UserContextServiceImpl
,它是接口IUserContextService
的实现。该服务基本上封装了Spring的SecurityContextHolder功能,只公开当前用户相关信息中通过其方法所需的部分,这样我们就不必在任何地方使用SecurityContextHolder。实现类用@Service(“userContextService”)注释。5) 接口
IUserContextService
位于持久性模块中。持久化模块中还有另一个类AppDependecyHeper
,它实现了ApplicationContextAware
,并通过调用appContext.getBean('UserContextService')返回UserContextService的具体实例
其中appContext
在应用程序初始化时保持ApplicationContext
。6) 现在,我们不想在持久性模块中公开Spring安全类(出于这里上下文之外的原因),也不想通过调用持久性层类
AppDependencyHelper
中applicationContext的getBean()方法来通过服务获取当前用户信息。然后使用此信息更新由EntityListener创建和修改的审核字段。
7) 实际应用程序只使用单个
ApplicationContext
,其中持久层类和web控制器都加载在一个spring上下文中。8) 应用程序运行时一切正常。但是,当我们的集成测试运行调用时,
appContext.getBean('userContextService')
失败并抛出NosuchBeanDefinitionException
,因为它无法找到名为“userContextService”的bean9) 现在,最后是我们集成测试的代码(仅给出相关细节),它位于
com.mycompany.persistence.embeddeddb
包中:
@Runwith(SpringJUnit4ClassRunner.class)
@ConfigurationContext
class MyEntityTest{
@Configuration
@ComponentScan("com.mycompany.persistence")
public static class Config{
.....
}
.....//code which eventually gives call to
AppDependencyHelper's method which in turn tries to retrieve userContextService Bean.
}
现在是问题:1) 为什么它无法检索bean?我尝试添加
com.mycompany.services
如下
@ComponentScan({“com.mycompany.persistence”,“com.mycompany.services”})
但是没有用。
2) 通过阅读我得到的任何信息,我能够理解的是,
@ContextConfiguration
需要提供XML文件或带注释的类或WebApplicationInitializer(在我的情况下,我们只有一个ApplicationContext),以便从@Configuration类创建ApplicationContext
。然而,我不能这样做,因为maven开始抱怨循环依赖性,这是正确的,因为我的@Service
注释类UserContextServiceImpl
位于web服务模块中,而web服务模块已经依赖于编写测试用例类的web持久性模块。3) 我能想到的唯一解决方案是将所有集成测试类移动到web服务模块,这样我就可以告诉
@ConfigurationContext
它应该从中创建应用程序上下文的所有类。我说得对吗
最后一点:当我运行测试时,ApplicationContext
类的类型是genericapplicationcontext
。当我运行应用程序时,它显然是annotateddedwebeapplicationcontext
请告诉我是否有解决此问题的方法?据我猜测,您试图在集成测试中使用web服务模块中的组件。如果是这样的话,那么您应该将集成测试用例移动到web服务模块中,正如您在问题中所建议的那样
编辑:您应该重新考虑您的设计,因为这里有一个循环依赖性问题:web服务
模块依赖于web持久性
,但是web持久性
中的IUserContextService
的实现可以在web服务
中找到
您可能应该将IUserContextService
(以及所有集成测试)移动到web服务
包中。确定。伟大的但是你能告诉我为什么即使我在ComponentScan中添加web服务包,它也不起作用吗?如果我添加更高级别的包(com.mycompany),其中包含其他组件(及其好友)类,那么在测试初始化时会出现不同的错误。但当我添加服务包时,它会初始化,但在运行时会中断。ComponentScan会忽略它吗?而且,即使假设我解决了这个问题,设置SecurityContext的问题仍然存在,我们出现这个问题的原因是我们不想将Spring安全依赖项放在持久化模块中。那么,将其移动到web服务以便在我的集成测试中启用Spring安全性的另一个原因是正确的吗?关于您的第一条评论:当Spring在您的@组件类中找不到@Autowire
d协作者时,您的测试在初始化时失败。当您尝试使用appContext.getBean('userContextService')
从完全构建的Spring容器中获取Bean时,测试在运行时失败,而这根本不存在,我可以重新启动