【问题标题】:Why NoSuchBeanDefinedException while running Spring Integration test为什么在运行 Spring Integration 测试时出现 NoSuchBeanDefinedException
【发布时间】:2016-03-26 21:52:42
【问题描述】:

我有一个 Spring Boot 项目,其中一位开发人员针对内存数据库编写了集成测试。在我提出问题之前,这里有一些背景:
我们有以下 Maven 模块:
1) web-persistence :存储所有实体和接口以及相应的实现。所有这些类都在包com.mycompany.persistence中。
2) web-services :它存储了我们所有的 rest 控制器和 spring 安全相关的类。这些都在包com.mycompany.services
3) web-services 模块对 web-persistence 模块有 maven 模块依赖。
4) 在 web-services 模块中,我们定义了一个服务UserContextServiceImpl,它是接口IUserContextService的实现。该服务基本上封装了 Spring 的 SecurityContextHolder 功能,只公开其方法所需的当前用户相关信息的那些部分,这样我们就不必在任何地方使用 SecurityContextHolder。实现类用@Service("userContextService")注解。
5) 接口IUserContextService 在持久化模块中。在持久化模块中还有另一个类AppDependecyHeper,它实现了ApplicationContextAware,并通过调用appContext.getBean('userContextService')返回UserContextService的具体实例,其中appContext在应用程序初始化时持有ApplicationContext
6) 现在我们不想在持久性模块中公开 Spring Security 类(因为这里没有上下文的原因),因此通过在持久层类 AppDependencyHelper 中调用 getBean() method of applicationContext 通过服务获取当前用户信息的上述安排.然后使用此信息更新审计字段 createdBy 和 modifiedBy 使用 EntityListener.
7) 实际应用程序仅使用单个 ApplicationContext,其中持久层类和 Web 控制器都加载在一个 Spring 上下文中。
8) 应用程序运行时一切正常。然而,当我们的集成测试运行调用 appContext.getBean('userContextService') 失败并抛出 NosuchBeanDefinitionException 因为它无法找到名为“userContextService”的 bean
9) 现在是位于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 文件或带注释的类或 WebApplicationInitializers(在我的情况下,因为我们只有一个 ApplicationContext)才能从@配置类。但是我不能这样做,因为 maven 开始抱怨循环依赖,这是正确的,因为我的 @Service 带注释的类 UserContextServiceImpl 在 web-services 模块中,该模块依赖于 web-persistence 模块已经编写了测试用例类。 3) 我能想到的唯一解决方案是将所有集成测试类移动到 Web 服务模块,这样我就可以告诉 @ConfigurationContext 它应该从中创建 ApplicationContext 的所有类。对吗?

最后一点:当我运行测试时,ApplicationContext 类的类型是 GenericApplciationContext。当我运行应用程序时,它显然是AnnotatedEmbeddedWebApplicationContext

如果有解决这个问题的办法,请告诉我?

【问题讨论】:

  • 只是为了确定:你的类是如何调用的,它实现了IUserContextService?你是坚持使用默认的 bean 命名约定还是使用 @Component(value = "userContextService") 给它一个替代的 bean 名称?
  • 我觉得我们忽略了参考 Spring 手册的正确部分来帮助您解决问题....同样,这个问题非常大

标签: spring integration-testing context-configuration


【解决方案1】:

据我猜测,您正在尝试在集成测试中使用 Web 服务模块中的组件。如果是这种情况,那么您应该将集成测试用例移至您的网络服务模块 - 正如您在问题中已经建议的那样。

编辑:你真的应该重新考虑你的设计,因为你在这里有一个循环依赖问题:你的web-service 模块依赖于web-persistence,但是你的IUserContextService 在@987654324 中的实现@ 在web-service 中找到。

您可能应该将您的 IUserContextService(以及您所有的集成测试)移动到您的 web-service 包中。

【讨论】:

  • 好的。伟大的。但是你能告诉我为什么即使我在 ComponentScan 中添加 web-services 包它也不起作用吗?如果我添加更高级别的包(com.mycompany),其中包含其他组件(及其朋友)类,它会在测试初始化​​时给出不同的错误。但是当我添加我的服务包时,它会初始化但在运行时会中断。 ComponentScan 是否忽略它?
  • 另外,即使假设我解决了这个问题,设置 SecurityContext 的问题仍然存在,我们遇到这个问题的原因是我们不想将 Spring Security 依赖项放在持久性模块中。那么将其移至 Web 服务以便在我的集成测试中启用 Spring Security 的另一个原因正确吗?
  • 关于您的第一条评论:当 Spring 在您的 @Component 类中找不到 @Autowired 协作者时,您的测试在初始化时失败。当您尝试使用完全不存在的 appContext.getBean('userContextService') 从完全构建的 Spring 容器中获取 Bean 时,您的测试在运行时失败
  • 好吧,我能够通过在持久性包中添加一个实现类来解决这个问题,该实现类实际上返回了硬编码字符串。不确定这是否是正确的方法,因为这不能称为纯粹的集成测试。
  • 确保您的 IUserContextService 存根位于 src/test/java
猜你喜欢
  • 2019-05-12
  • 2020-05-07
  • 1970-01-01
  • 2016-08-19
  • 2019-07-16
  • 2019-05-20
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
相关资源
最近更新 更多