【问题标题】:Spring Test with dependency Injection of real objects and mocks带有真实对象和模拟的依赖注入的 Spring 测试
【发布时间】:2021-11-09 10:26:17
【问题描述】:

我有一个测试用例,其中基于布尔属性,我们决定在应用程序启动时创建 2 个 Spring Bean 中的哪一个。 为简单起见,我们称它们为ProfileServiceA 和ProfileServiceB。 当布尔属性设置为false(默认值)时,它会创建ProfileServiceA,当它是true 时,它会创建ProfileServiceB。 这是在使用@Configuration 注释的配置类中完成的。

我的测试非常简单,我想验证当我们的应用程序基于该属性启动时,Spring 上下文中加载了哪一个 Bean。
对于这些 Bean 中的每一个,当我们创建它们时,构造函数会获取多个对象以便实例化。
我使用@MockBean 注释的大多数对象,因为它们只在构造函数中被指向,就像我们通常使用依赖注入所做的那样,这对我来说不是问题。
这些属性之一不仅在构造函数中被指出,而且实际上被用于构建其中一个字段。
在 ProfileService 的构造函数中,我们这样做:

this.url = securityProperties.getProfile().getProtocol() + "://" + securityProperties.getProfile().getHost() + ":" + securityProperties.getProfile().getPort() + "/" + securityProperties.getProfile().getEndpoint();

SecurityProperties 类具有内部静态类 Profile,因此当应用程序上下文开始加载并且此 Bean 在构造函数中被实例化时(甚至在使用 @987654332 注释的方法之前@) 我在 NullPointerException 上失败,因为对象 Profile 仍然为空(SecurityProperties 不是因为它被 @MockBean 注释)。

SecurityProperties 及其内部静态类 Profile 未定义为 Bean,但我仍然尝试将测试类中的 Profile 对象也设置为 @MockBean 或 @Mock 但这并没有解决问题。

我想我可能需要将“真实”对象注入到上下文中,但我找不到关于如何将带有模拟对象的“真实”对象注入到 Autowired Spring Bean 的 wiki/docs。

SecurityProperties 不是 Spring Bean,而是常规数据对象 (POJO)。

【问题讨论】:

  • 所以你不使用依赖注入获取ProfileService而是自己调用构造函数?是否可以在服务上使用@Profile("myProfile") 注释来自动创建具有自动装配依赖关系的所需服务?
  • 我确实使用依赖注入。在测试类中,ProfileService 用“Autowired”注释。应该注入到该 Bean 的构造函数中的字段都用“MockBean”注释(如 SecurityProperties 类)。它们在构造函数中不为空,只有 Profile 类,它是 SecurityProperties 内部的内部静态类。

标签: java spring testing mocking


【解决方案1】:

您可以在测试代码中实现BeanPostProcessor interface。在 postProcessBeforeInitialization 的实现中,如果当前 bean 名称是 securityProperties(或您的 SecurityProperties bean 具有的任何名称),则模拟 SecurityProperties::getProfile() 的行为以返回实际的 Profile 实例以避免 NPE。

这是可行的,因为ProfileService 依赖于SecurityProperties,因此后者将首先启动,然后在 ProfileService 的实例化之前调用您的 postProcessBeforeInitialization

【讨论】:

  • 我相信这不会解决我的问题,我通过说 SecurityProperties 类不是实际的 Spring Bean 来编辑我的问题。为这个类添加一个接口只是为了支持我们的一个测试似乎不是正确的方法。我真的有点困惑,为什么将带有“模拟”对象的“真实”对象注入 Spring Bean 的构造函数有点困难。
  • 就像我说的那样,您的测试类应该实现该接口,而不是 SecurityProperties 类,因为这些方法会在应用程序上下文中为所有 bean 调用。但如果 SecurityProperties 不是 bean,这将不起作用。我想知道为什么它不是豆子。在您的问题中添加有关该类的更多详细信息,它是如何被实例化和初始化的,它是如何传递给服务的。他们说,如果一个组件变得难以测试,通常意味着设计需要改进。你也可以考虑一下
猜你喜欢
  • 1970-01-01
  • 2013-01-16
  • 1970-01-01
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多