@MockitoBean 和 @MockitoSpyBean
@MockitoBean 和
@MockitoSpyBean
可用于测试类中,分别使用 Mockito 的 mock 或 spy 来覆盖测试的 ApplicationContext 中的某个 Bean。在后一种情况下,原始 Bean 的早期实例会被捕获并由 spy 包装。
这些注解可以按以下方式应用。
-
在测试类或其任意父类中的非静态字段上。
-
在
@Nested测试类的外部类中的非静态字段上,或在@Nested测试类之上类型层次结构或外部类层次结构中的任意类中。 -
在测试类的类型级别上,或在测试类之上的类型层次结构中的任何超类或所实现的接口上。
-
在
@Nested测试类的外部类上,或在该@Nested测试类之上类型层次结构或外部类层次结构中的任意类或接口上,以类型级别进行标注。
当在字段上声明 @MockitoBean 或 @MockitoSpyBean 时,要模拟(mock)或监视(spy)的 Bean 将根据被注解字段的类型进行推断。如果在 ApplicationContext 中存在多个候选 Bean,则可以在该字段上声明 @Qualifier 注解以帮助消除歧义。如果没有 @Qualifier 注解,将使用被注解字段的名称作为备用限定符(fallback qualifier)。另外,你也可以通过设置注解中的 value 或 name 属性,显式指定要模拟或监视的 Bean 名称。
当在类型级别声明 @MockitoBean 或 @MockitoSpyBean 时,必须通过注解中的 types 属性提供要模拟(mock)或侦听(spy)的 Bean(或多个 Bean)的类型——例如 @MockitoBean(types = {OrderService.class, UserService.class})。如果 ApplicationContext 中存在多个候选者,您可以通过设置 name 属性显式指定要模拟或侦听的 Bean 名称。但请注意,如果配置了显式的 Bean name,则 types 属性必须仅包含单一类型——例如 @MockitoBean(name = "ps1", types = PrintingService.class)。
为了支持模拟(mock)配置的复用,@MockitoBean 和 @MockitoSpyBean 可用作元注解(meta-annotations),以创建自定义的组合注解(composed annotations)——例如,将通用的模拟或间谍(spy)配置定义在一个注解中,以便在整个测试套件中重复使用。@MockitoBean 和 @MockitoSpyBean 也可以作为可重复注解(repeatable annotations)在类型级别上使用——例如,按名称模拟或监视多个 Bean。
|
限定符(包括字段的名称)用于确定是否需要创建一个独立的 |
|
将 有关更多详细信息和示例,请参见 带有 Bean 覆盖的上下文层次结构。 |
每个注解还定义了特定于 Mockito 的属性,用于微调模拟行为。
@MockitoBean 注解使用 REPLACE_OR_CREATE
bean 覆盖策略。
如果对应的 bean 不存在,将创建一个新的 bean。不过,你可以通过将 REPLACE 属性设置为 enforceOverride 来切换到 true 策略——
例如:@MockitoBean(enforceOverride = true)。
@MockitoSpyBean 注解使用 WRAP
策略,
并将原始实例包装在一个 Mockito spy 中。该策略要求必须恰好存在一个候选 bean。
|
正如 Mockito 文档中所述,有时使用 为避免此类不希望出现的副作用,请考虑使用
|
|
当使用 同样地,当使用 当使用 同样地,当使用 此外, |
|
对 因此,这些字段可以是 |
@MockitoBean示例
以下示例展示了如何使用 @MockitoBean 注解的默认行为。
-
Java
@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {
@MockitoBean (1)
CustomService customService;
// tests...
}
| 1 | 使用 Mockito mock 替换类型为 CustomService 的 bean。 |
在上面的示例中,我们正在为 CustomService 创建一个模拟对象。如果存在多个该类型的 Bean,则会考虑名为 customService 的 Bean。否则,测试将失败,您需要提供某种限定符来指明您想要覆盖哪一个 CustomService Bean。如果不存在这样的 Bean,系统将使用自动生成的 Bean 名称创建一个 Bean。
以下示例使用按名称查找,而不是按类型查找。如果不存在名为 service 的 bean,则会创建一个。
-
Java
@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {
@MockitoBean("service") (1)
CustomService customService;
// tests...
}
| 1 | 将名为 service 的 bean 替换为一个 Mockito mock。 |
以下 @SharedMocks 注解按类型注册了两个模拟对象,按名称注册了一个模拟对象。
-
Java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@MockitoBean(types = {OrderService.class, UserService.class}) (1)
@MockitoBean(name = "ps1", types = PrintingService.class) (2)
public @interface SharedMocks {
}
| 1 | 按类型注册 OrderService 和 UserService 的模拟对象。 |
| 2 | 按名称注册 PrintingService 的模拟对象。 |
以下演示了如何在测试类上使用 @SharedMocks。
-
Java
@SpringJUnitConfig(TestConfig.class)
@SharedMocks (1)
class BeanOverrideTests {
@Autowired OrderService orderService; (2)
@Autowired UserService userService; (2)
@Autowired PrintingService ps1; (2)
// Inject other components that rely on the mocks.
@Test
void testThatDependsOnMocks() {
// ...
}
}
| 1 | 通过自定义的 @SharedMocks 注解注册通用的模拟对象。 |
| 2 | 可选地注入模拟对象以对其进行打桩或验证。 |
这些模拟对象也可以注入到 @Configuration 类或其他与测试相关的组件中,这些组件位于 ApplicationContext 中,以便使用 Mockito 的桩(stubbing)API 对它们进行配置。 |
@MockitoSpyBean示例
以下示例展示了如何使用 @MockitoSpyBean 注解的默认行为。
-
Java
@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {
@MockitoSpyBean (1)
CustomService customService;
// tests...
}
| 1 | 使用 Mockito 的 spy 包装类型为 CustomService 的 bean。 |
在上面的示例中,我们正在包装类型为 CustomService 的 bean。如果存在多个该类型的 bean,则会使用名为 customService 的 bean。否则,测试将失败,您需要提供某种限定符(qualifier)来指明您想要监视(spy)哪一个 CustomService bean。
以下示例使用按名称查找,而不是按类型查找。
-
Java
@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {
@MockitoSpyBean("service") (1)
CustomService customService;
// tests...
}
| 1 | 使用 Mockito spy 包装名为 service 的 bean。 |
以下 @SharedSpies 注解按类型注册了两个间谍(spy),并按名称注册了一个间谍(spy)。
-
Java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@MockitoSpyBean(types = {OrderService.class, UserService.class}) (1)
@MockitoSpyBean(name = "ps1", types = PrintingService.class) (2)
public @interface SharedSpies {
}
| 1 | 按类型注册 OrderService 和 UserService 的间谍(spies)。 |
| 2 | 按名称注册 PrintingService 的间谍(spy)。 |
以下演示了如何在测试类上使用 @SharedSpies。
-
Java
@SpringJUnitConfig(TestConfig.class)
@SharedSpies (1)
class BeanOverrideTests {
@Autowired OrderService orderService; (2)
@Autowired UserService userService; (2)
@Autowired PrintingService ps1; (2)
// Inject other components that rely on the spies.
@Test
void testThatDependsOnMocks() {
// ...
}
}
| 1 | 通过自定义的 @SharedSpies 注解注册通用的间谍(spies)。 |
| 2 | 可选地注入间谍(spies)以对其进行打桩(stub)或验证(verify)。 |
这些间谍(spies)也可以被注入到 @Configuration 类或 ApplicationContext 中的其他测试相关组件中,以便使用 Mockito 的桩(stubbing)API 对它们进行配置。 |