@MockitoBean
和 @MockitoSpyBean
@MockitoBean
and @MockitoSpyBean
@MockitoBean 和 @MockitoSpyBean 可以在测试类中使用,以分别用 Mockito 的 mock 或 spy 来覆盖测试的 ApplicationContext
中的一个 bean。在后者的情况下,原始 bean 的早期实例会被捕获并被 spy 包装。
注释可以通过以下方式应用。
-
在测试类或其任何超类中的非静态字段上。
-
在
@Nested
测试类的封闭类中的非静态字段上,或在类型层次结构或封闭类层次结构中位于@Nested
测试类之上的任何类中。 -
在测试类或其任何超类或实现的接口的类型级别上,位于测试类之上的类型层次结构中。
-
在
@Nested
测试类的封闭类的类型级别上,或在类型层次结构或封闭类层次结构中位于@Nested
测试类之上的任何类或接口上。
当 @MockitoBean
或 @MockitoSpyBean
被声明在一个字段上时,要模拟或监视的 bean 是根据被注解字段的类型推断的。如果在 ApplicationContext
中存在多个候选项,可以在字段上声明 @Qualifier
注解以帮助消除歧义。在没有 @Qualifier
注解的情况下,将使用被注解字段的名称作为 后备限定符。或者,您可以通过在注解中设置 value
或 name
属性来显式指定要模拟或监视的 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
创建的对象类型的单例模拟。
当使用 @MockitoSpyBean
为 FactoryBean
创建一个间谍时,将为 FactoryBean
创建的对象创建一个间谍,而不是为 FactoryBean
本身创建。
@MockitoBean
和 @MockitoSpyBean
字段的可见性没有限制。
因此,这些字段可以是 public
、protected
、包私有(默认可见性)或 private
,具体取决于项目的需求或编码实践。
@MockitoBean
示例
以下示例展示了如何使用 @MockitoBean
注解的默认行为。
- Java
@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {
@MockitoBean 1
CustomService customService;
// tests...
}
用 Mockito 模拟替换类型为
CustomService
的 bean。
在上面的例子中,我们为 CustomService
创建了一个模拟。如果存在多个该类型的 bean,则考虑名为 customService
的 bean。否则,测试将失败,您需要提供某种限定符来识别您想要覆盖的 CustomService
bean。如果不存在这样的 bean,将创建一个具有自动生成的 bean 名称的 bean。
以下示例使用按名称查找,而不是按类型查找。如果不存在名为 service
的 bean,则会创建一个。
- Java
@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {
@MockitoBean("service") 1
CustomService customService;
// 测试...
}
用 Mockito mock 替换名为
service
的 bean。
以下 @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 {
}
按类型注册
OrderService
和UserService
的模拟对象。按名称注册
PrintingService
的模拟对象。
以下演示了如何在测试类上使用 @SharedMocks
。
- Java
@SpringJUnitConfig(TestConfig.class)
@SharedMocks 1
class BeanOverrideTests {
@Autowired OrderService orderService; 2
@Autowired UserService userService; 2
@Autowired PrintingService ps1; 2
// 注入其他依赖于模拟对象的组件。
@Test
void testThatDependsOnMocks() {
// ...
}
}
通过自定义
@SharedMocks
注解注册公共模拟对象。可选地注入模拟对象以 存根 或 验证 它们。
这些模拟对象也可以注入到 @Configuration
类或 ApplicationContext
中的其他与测试相关的组件,以便使用 Mockito 的存根 API 对它们进行配置。
@MockitoSpyBean
示例
以下示例展示了如何使用 @MockitoSpyBean
注解的默认行为。
- Java
@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {
@MockitoSpyBean 1
CustomService customService;
// tests...
}
用 Mockito spy 包装类型为
CustomService
的 bean。
在上面的例子中,我们正在包装类型为 CustomService
的 bean。如果存在多个该类型的 bean,则被命名为 customService
的 bean 将被考虑。否则,测试将失败,您需要提供某种限定符以识别您想要监视的 CustomService
bean。
以下示例使用按名称查找,而不是按类型查找。
- Java
@SpringJUnitConfig(TestConfig.class)
class BeanOverrideTests {
@MockitoSpyBean("service") 1
CustomService customService;
// tests...
}
用 Mockito spy 包装名为
service
的 bean。
以下 @SharedSpies
注解通过类型注册了两个间谍,通过名称注册了一个间谍。
- Java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@MockitoSpyBean(types = {OrderService.class, UserService.class}) 1
@MockitoSpyBean(name = "ps1", types = PrintingService.class) 2
public @interface SharedSpies {
}
按类型注册
OrderService
和UserService
的间谍。按名称注册
PrintingService
的间谍。
以下演示了如何在测试类上使用 @SharedSpies
。
- Java
@SpringJUnitConfig(TestConfig.class)
@SharedSpies 1
class BeanOverrideTests {
@Autowired OrderService orderService; 2
@Autowired UserService userService; 2
@Autowired PrintingService ps1; 2
// 注入其他依赖于间谍的组件。
@Test
void testThatDependsOnMocks() {
// ...
}
}
通过自定义
@SharedSpies
注解注册公共间谍。可选地注入间谍以 stub 或 verify 它们。
间谍也可以注入到 @Configuration
类或 ApplicationContext
中的其他测试相关组件,以便使用 Mockito 的存根 API 对它们进行配置。