此版本仍在开发中,尚未被视为稳定版。如需最新稳定版本,请使用 Spring Framework 7.0.6spring-doc.cadn.net.cn

@TestBean

@TestBean 用于测试类中的非静态字段,以使用工厂方法提供的实例覆盖测试的ApplicationContext中的特定 Bean。spring-doc.cadn.net.cn

关联的工厂方法名称源自被注解字段的名称,或者如果指定了 Bean 名称,则使用该名称。该工厂方法必须是 static 的,不接受任何参数,并且其返回类型必须与要覆盖的 Bean 类型兼容。为了使意图更加明确,或者如果您希望使用不同的方法名,该注解也允许显式指定一个具体的方法名称。spring-doc.cadn.net.cn

默认情况下,会使用带注解字段的类型来搜索候选 Bean 以进行覆盖。 如果存在多个匹配的候选 Bean,可以提供 @Qualifier 注解来缩小要覆盖的候选范围。 或者,其 Bean 名称与字段名称相匹配的候选 Bean 也会被选中。spring-doc.cadn.net.cn

如果对应的 bean 不存在,将会创建一个 bean。然而,如果您希望在对应的 bean 不存在时让测试失败,可以将 enforceOverride 属性设置为 true —— 例如,@TestBean(enforceOverride = true)spring-doc.cadn.net.cn

要使用按名称覆盖而非按类型覆盖,请指定注解的 name 属性。spring-doc.cadn.net.cn

限定符(包括字段的名称)用于确定是否需要创建一个单独的ApplicationContext。如果您在多个测试中使用此功能来覆盖同一个 bean,请确保字段命名保持一致,以避免创建不必要的上下文。spring-doc.cadn.net.cn

@TestBean@ContextHierarchy 结合使用可能会导致不良结果, 因为默认情况下每个 @TestBean 都会应用于所有上下文层级。 为确保某个特定的 @TestBean 仅应用于单个上下文层级, 请将 contextName 属性设置为与已配置的 @ContextConfiguration 名称相匹配—— 例如:@TestBean(contextName = "app-config")spring-doc.cadn.net.cn

有关更多详细信息和示例,请参见 带有 Bean 覆盖的上下文层次结构spring-doc.cadn.net.cn

@TestBean 字段或工厂方法的可见性没有任何限制。spring-doc.cadn.net.cn

因此,这些字段和方法可以根据项目的需求或编码规范,声明为 publicprotected、包私有(默认可见性)或 privatespring-doc.cadn.net.cn

以下示例展示了如何使用 @TestBean 注解的默认行为:spring-doc.cadn.net.cn

class OverrideBeanTests {
	@TestBean (1)
	CustomService customService;

	// test case body...

	static CustomService customService() { (2)
		return new MyFakeCustomService();
	}
}
1 标记一个字段,以使用类型为 CustomService 的 bean 进行覆盖。
2 该静态方法的结果将被用作实例并注入到字段中。

在上面的示例中,我们正在覆盖类型为 CustomService 的 bean。如果存在多个该类型的 bean,则会使用名为 customService 的 bean。否则,测试将失败,您需要提供某种限定符来指明您想要覆盖的是哪一个 CustomService bean。spring-doc.cadn.net.cn

以下示例使用按名称查找,而不是按类型查找:spring-doc.cadn.net.cn

class OverrideBeanTests {
	@TestBean(name = "service", methodName = "createCustomService") (1)
	CustomService customService;

	// test case body...

	static CustomService createCustomService() { (2)
		return new MyFakeCustomService();
	}
}
1 标记一个字段,用于覆盖名为 service 的 bean,并指定工厂方法名为 createCustomService
2 该静态方法的结果将被用作实例并注入到字段中。

为了定位要调用的工厂方法,Spring 会在声明了 @TestBean 字段的类、其任意一个父类或所实现的任何接口中进行搜索。如果 @TestBean 字段声明在一个 @Nested 测试类中,则还会搜索其外部类的继承层次结构。spring-doc.cadn.net.cn

或者,可以通过完全限定的方法名引用外部类中的工厂方法,其语法为 <fully-qualified class name>#<method name> —— 例如,methodName = "org.example.TestUtils#createCustomService"spring-doc.cadn.net.cn

只有单例Bean可以被覆盖。任何尝试覆盖非单例Bean的行为都会导致异常。spring-doc.cadn.net.cn

当覆盖由 FactoryBean 创建的 bean 时,该 FactoryBean 将被替换为一个单例 bean,该单例 bean 对应于 @TestBean 工厂方法返回的值。spring-doc.cadn.net.cn