@TestBean
@TestBean
@TestBean 用于测试类中的非静态字段,以通过工厂方法提供的实例覆盖测试的 ApplicationContext
中的特定 bean。
关联的工厂方法名称源自注解字段的名称,或者如果指定了,则源自 bean 名称。工厂方法必须是 static
,不接受任何参数,并且返回类型必须与要覆盖的 bean 的类型兼容。为了使事情更加明确,或者如果您更愿意使用不同的名称,注解允许提供特定的方法名称。
默认情况下,注解字段的类型用于搜索候选 bean 以进行覆盖。如果多个候选项匹配,可以提供 @Qualifier
来缩小覆盖的候选项。或者,候选项的 bean 名称与字段名称匹配也会匹配。
如果相应的 bean 不存在,将会创建一个 bean。然而,如果您希望在相应的 bean 不存在时测试失败,可以将 enforceOverride
属性设置为 true
– 例如,@TestBean(enforceOverride = true)
。
要使用按名称覆盖而不是按类型覆盖,请指定注释的 name
属性。
限定符,包括字段的名称,用于确定是否需要创建一个单独的 ApplicationContext
。如果您使用此功能在多个测试中覆盖相同的 bean,请确保一致命名字段,以避免创建不必要的上下文。
@TestBean
字段或工厂方法的可见性没有限制。
因此,这些字段和方法可以是 public
、protected
、包私有(默认可见性)或 private
,具体取决于项目的需求或编码实践。
以下示例展示了如何使用 @TestBean
注解的默认行为:
- Java
class OverrideBeanTests {
@TestBean 1
CustomService customService;
// 测试用例主体...
static CustomService customService() { 2
return new MyFakeCustomService();
}
}
标记一个字段以覆盖类型为
CustomService
的 bean。此静态方法的结果将用作实例并注入到字段中。
在上面的例子中,我们正在覆盖类型为 CustomService
的 bean。如果存在多个该类型的 bean,则会考虑名为 customService
的 bean。否则,测试将失败,您需要提供某种限定符以识别您想要覆盖的 CustomService
bean。
以下示例使用按名称查找,而不是按类型查找:
- Java
class OverrideBeanTests {
@TestBean(name = "service", methodName = "createCustomService") 1
CustomService customService;
// 测试用例主体...
static CustomService createCustomService() { 2
return new MyFakeCustomService();
}
}
标记一个字段以覆盖名为
service
的 bean,并指定工厂方法名为createCustomService
。这个静态方法的结果将作为实例并注入到字段中。
为了定位要调用的工厂方法,Spring 会在声明 @TestBean
字段的类中、其超类中或任何实现的接口中进行搜索。如果 @TestBean
字段是在 @Nested
测试类中声明的,则还会搜索封闭类层次结构。
或者,可以通过其完全限定的方法名引用外部类中的工厂方法,语法为 <完全限定类名>#<方法名>
– 例如,methodName = "org.example.TestUtils#createCustomService"
。
只有 singleton bean 可以被覆盖。任何尝试覆盖非单例 bean 的行为都会导致异常。
当覆盖由 FactoryBean
创建的 bean 时,FactoryBean
将被替换为与 @TestBean
工厂方法返回的值对应的单例 bean。