跳到主要内容

@MockitoBean@MockitoSpyBean

ChatGPT-4o-mini 中英对照 @MockitoBean and @MockitoSpyBean @MockitoBean and @MockitoSpyBean

@MockitoBean@MockitoSpyBean 可以在测试类中使用,以分别用 Mockito 的 mockspy 来覆盖测试的 ApplicationContext 中的一个 bean。在后者的情况下,原始 bean 的早期实例会被捕获并被 spy 包装。

注释可以通过以下方式应用。

  • 在测试类或其任何超类中的非静态字段上。

  • @Nested 测试类的封闭类中的非静态字段上,或在类型层次结构或封闭类层次结构中位于 @Nested 测试类之上的任何类中。

  • 在测试类或其任何超类或实现的接口的类型级别上,位于测试类之上的类型层次结构中。

  • @Nested 测试类的封闭类的类型级别上,或在类型层次结构或封闭类层次结构中位于 @Nested 测试类之上的任何类或接口上。

@MockitoBean@MockitoSpyBean 被声明在一个字段上时,要模拟或监视的 bean 是根据被注解字段的类型推断的。如果在 ApplicationContext 中存在多个候选项,可以在字段上声明 @Qualifier 注解以帮助消除歧义。在没有 @Qualifier 注解的情况下,将使用被注解字段的名称作为 后备限定符。或者,您可以通过在注解中设置 valuename 属性来显式指定要模拟或监视的 bean 名称。

@MockitoBean@MockitoSpyBean 在类型级别声明时,必须通过注解中的 types 属性提供要模拟或监视的 bean(或 beans)的类型 – 例如,@MockitoBean(types = {OrderService.class, UserService.class})。如果在 ApplicationContext 中存在多个候选项,可以通过设置 name 属性显式指定要模拟或监视的 bean 名称。然而,请注意,如果配置了显式的 bean name,则 types 属性必须只包含一个类型 – 例如,@MockitoBean(name = "ps1", types = PrintingService.class)

为了支持模拟配置的重用,可以使用 @MockitoBean@MockitoSpyBean 作为元注解来创建自定义的 组合注解 —— 例如,定义在单个注解中可以重用的公共模拟或间谍配置,这样可以在整个测试套件中使用。@MockitoBean@MockitoSpyBean 也可以作为可重复注解在类型级别使用 —— 例如,通过名称模拟或间谍多个 bean。

注意

限定符,包括字段的名称,用于确定是否需要创建一个单独的 ApplicationContext。如果您使用此功能在多个测试类中模拟或监视相同的 bean,请确保一致命名字段,以避免创建不必要的上下文。

每个注解还定义了 Mockito 特定的属性,以微调模拟行为。

@MockitoBean 注解使用 REPLACE_OR_CREATE 策略进行 bean 覆盖。如果对应的 bean 不存在,将会创建一个新的 bean。然而,您可以通过将 enforceOverride 属性设置为 true 来切换到 REPLACE 策略 – 例如,@MockitoBean(enforceOverride = true)

@MockitoSpyBean 注解使用 WRAP 策略,原始实例被包装在一个 Mockito spy 中。该策略要求存在恰好一个候选 bean。

提示

只有 singleton Bean 可以被覆盖。任何尝试覆盖非单例 Bean 的行为将导致异常。

当使用 @MockitoBean 来模拟由 FactoryBean 创建的 Bean 时,FactoryBean 将被替换为该 FactoryBean 创建的对象类型的单例模拟。

当使用 @MockitoSpyBeanFactoryBean 创建一个间谍时,将为 FactoryBean 创建的对象创建一个间谍,而不是为 FactoryBean 本身创建。

备注

@MockitoBean@MockitoSpyBean 字段的可见性没有限制。

因此,这些字段可以是 publicprotected、包私有(默认可见性)或 private,具体取决于项目的需求或编码实践。

@MockitoBean 示例

以下示例展示了如何使用 @MockitoBean 注解的默认行为。

@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {

@MockitoBean 1
CustomService customService;

// tests...
}
java
  • 用 Mockito 模拟替换类型为 CustomService 的 bean。

在上面的例子中,我们为 CustomService 创建了一个模拟。如果存在多个该类型的 bean,则考虑名为 customService 的 bean。否则,测试将失败,您需要提供某种限定符来识别您想要覆盖的 CustomService bean。如果不存在这样的 bean,将创建一个具有自动生成的 bean 名称的 bean。

以下示例使用按名称查找,而不是按类型查找。如果不存在名为 service 的 bean,则会创建一个。

@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {

@MockitoBean("service") 1
CustomService customService;

// 测试...

}
java
  • 用 Mockito mock 替换名为 service 的 bean。

以下 @SharedMocks 注解通过类型注册了两个模拟对象,并通过名称注册了一个模拟对象。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@MockitoBean(types = {OrderService.class, UserService.class}) 1
@MockitoBean(name = "ps1", types = PrintingService.class) 2
public @interface SharedMocks {
}
java
  • 按类型注册 OrderServiceUserService 的模拟对象。

  • 按名称注册 PrintingService 的模拟对象。

以下演示了如何在测试类上使用 @SharedMocks

@SpringJUnitConfig(TestConfig.class)
@SharedMocks 1
class BeanOverrideTests {

@Autowired OrderService orderService; 2

@Autowired UserService userService; 2

@Autowired PrintingService ps1; 2

// 注入其他依赖于模拟对象的组件。

@Test
void testThatDependsOnMocks() {
// ...
}
}
java
  • 通过自定义 @SharedMocks 注解注册公共模拟对象。

  • 可选地注入模拟对象以 存根验证 它们。

提示

这些模拟对象也可以注入到 @Configuration 类或 ApplicationContext 中的其他与测试相关的组件,以便使用 Mockito 的存根 API 对它们进行配置。

@MockitoSpyBean 示例

以下示例展示了如何使用 @MockitoSpyBean 注解的默认行为。

@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {

@MockitoSpyBean 1
CustomService customService;

// tests...
}
java
  • 用 Mockito spy 包装类型为 CustomService 的 bean。

在上面的例子中,我们正在包装类型为 CustomService 的 bean。如果存在多个该类型的 bean,则被命名为 customService 的 bean 将被考虑。否则,测试将失败,您需要提供某种限定符以识别您想要监视的 CustomService bean。

以下示例使用按名称查找,而不是按类型查找。

@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {

@MockitoSpyBean("service") 1
CustomService customService;

// tests...
}
java
  • 用 Mockito spy 包装名为 service 的 bean。

以下 @SharedSpies 注解通过类型注册了两个间谍,通过名称注册了一个间谍。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@MockitoSpyBean(types = {OrderService.class, UserService.class}) 1
@MockitoSpyBean(name = "ps1", types = PrintingService.class) 2
public @interface SharedSpies {
}
java
  • 按类型注册 OrderServiceUserService 的间谍。

  • 按名称注册 PrintingService 的间谍。

以下演示了如何在测试类上使用 @SharedSpies

@SpringJUnitConfig(TestConfig.class)
@SharedSpies 1
class BeanOverrideTests {

@Autowired OrderService orderService; 2

@Autowired UserService userService; 2

@Autowired PrintingService ps1; 2

// 注入其他依赖于间谍的组件。

@Test
void testThatDependsOnMocks() {
// ...
}
}
java
  • 通过自定义 @SharedSpies 注解注册公共间谍。

  • 可选地注入间谍以 stubverify 它们。

提示

间谍也可以注入到 @Configuration 类或 ApplicationContext 中的其他测试相关组件,以便使用 Mockito 的存根 API 对它们进行配置。