Context Configuration Inheritance

@ContextConfiguration 支持布尔类型的 inheritLocationsinheritInitializers 属性,这些属性表示是否应继承超类声明的资源位置或组件类和 context 初始化器。这两个标志的默认值为 true。这意味着测试类会继承超类声明的资源位置或组件类以及 context 初始化器。具体来说,测试类的资源位置或组件类追加到超类声明的资源位置或带注解的类的列表。类似地,某个测试类的初始化器会添加到按测试超类定义的初始化器集合中。因此,子类可以选择扩展资源位置、组件类或 context 初始化器。

@ContextConfiguration supports boolean inheritLocations and inheritInitializers attributes that denote whether resource locations or component classes and context initializers declared by superclasses should be inherited. The default value for both flags is true. This means that a test class inherits the resource locations or component classes as well as the context initializers declared by any superclasses. Specifically, the resource locations or component classes for a test class are appended to the list of resource locations or annotated classes declared by superclasses. Similarly, the initializers for a given test class are added to the set of initializers defined by test superclasses. Thus, subclasses have the option of extending the resource locations, component classes, or context initializers.

如果 @ContextConfiguration 中的 inheritLocationsinheritInitializers 属性设置为 false,该测试类的资源位置或组件类以及 context 初始化器将遮蔽并有效替换超类定义的配置。

If the inheritLocations or inheritInitializers attribute in @ContextConfiguration is set to false, the resource locations or component classes and the context initializers, respectively, for the test class shadow and effectively replace the configuration defined by superclasses.

从 Spring Framework 5.3 开始,还可以从封闭类继承测试配置。请参阅 @Nested test class configuration 了解详情。

As of Spring Framework 5.3, test configuration may also be inherited from enclosing classes. See @Nested test class configuration for details.

在使用 XML 资源位置的下一个示例中,ExtendedTestApplicationContext 按如下顺序从 base-config.xmlextended-config.xml 中加载。因此,extended-config.xml 中定义的 bean 可以覆盖(即替换)base-config.xml 中定义的 bean。以下示例说明了一个类如何可以扩展另一个类,并同时使用自己的配置文件和超类的配置文件:

In the next example, which uses XML resource locations, the ApplicationContext for ExtendedTest is loaded from base-config.xml and extended-config.xml, in that order. Beans defined in extended-config.xml can, therefore, override (that is, replace) those defined in base-config.xml. The following example shows how one class can extend another and use both its own configuration file and the superclass’s configuration file:

Java
@ExtendWith(SpringExtension.class)
// ApplicationContext will be loaded from "/base-config.xml"
// in the root of the classpath
@ContextConfiguration("/base-config.xml") 1
class BaseTest {
	// class body...
}

// ApplicationContext will be loaded from "/base-config.xml" and
// "/extended-config.xml" in the root of the classpath
@ContextConfiguration("/extended-config.xml") 2
class ExtendedTest extends BaseTest {
	// class body...
}
1 Configuration file defined in the superclass.
2 Configuration file defined in the subclass.
Kotlin
@ExtendWith(SpringExtension::class)
// ApplicationContext will be loaded from "/base-config.xml"
// in the root of the classpath
@ContextConfiguration("/base-config.xml") (1)
open class BaseTest {
	// class body...
}

// ApplicationContext will be loaded from "/base-config.xml" and
// "/extended-config.xml" in the root of the classpath
@ContextConfiguration("/extended-config.xml") (2)
class ExtendedTest : BaseTest() {
	// class body...
}
3 Configuration file defined in the superclass.
4 Configuration file defined in the subclass.

类似地,在使用组件类的下一个示例中,ExtendedTestApplicationContext 按如下顺序从 BaseConfigExtendedConfig 类中加载。因此,ExtendedConfig 中定义的 bean 可以覆盖(即替换)BaseConfig 中定义的 bean。以下示例说明了一个类如何可以扩展另一个类,并同时使用自己的配置类和超类的配置类:

Similarly, in the next example, which uses component classes, the ApplicationContext for ExtendedTest is loaded from the BaseConfig and ExtendedConfig classes, in that order. Beans defined in ExtendedConfig can, therefore, override (that is, replace) those defined in BaseConfig. The following example shows how one class can extend another and use both its own configuration class and the superclass’s configuration class:

Java
// ApplicationContext will be loaded from BaseConfig
@SpringJUnitConfig(BaseConfig.class) (1)
class BaseTest {
	// class body...
}

// ApplicationContext will be loaded from BaseConfig and ExtendedConfig
@SpringJUnitConfig(ExtendedConfig.class) (2)
class ExtendedTest extends BaseTest {
	// class body...
}
1 Configuration class defined in the superclass.
2 Configuration class defined in the subclass.
Kotlin
// ApplicationContext will be loaded from BaseConfig
@SpringJUnitConfig(BaseConfig::class) (1)
open class BaseTest {
	// class body...
}

// ApplicationContext will be loaded from BaseConfig and ExtendedConfig
@SpringJUnitConfig(ExtendedConfig::class) (2)
class ExtendedTest : BaseTest() {
	// class body...
}
3 Configuration class defined in the superclass.
4 Configuration class defined in the subclass.

在使用 context 初始化器的下一个示例中,ExtendedTestApplicationContext 使用 BaseInitializerExtendedInitializer 初始化。然而请注意,初始化器被调用的顺序取决于它们是否实现了 Spring 的 Ordered 接口,或者是否用 Spring 的 @Order 注解或标准的 @Priority 注解进行了注解。以下示例说明了一个类如何可以扩展另一个类,并同时使用自己的初始化器和超类的初始化器:

In the next example, which uses context initializers, the ApplicationContext for ExtendedTest is initialized by using BaseInitializer and ExtendedInitializer. Note, however, that the order in which the initializers are invoked depends on whether they implement Spring’s Ordered interface or are annotated with Spring’s @Order annotation or the standard @Priority annotation. The following example shows how one class can extend another and use both its own initializer and the superclass’s initializer:

Java
// ApplicationContext will be initialized by BaseInitializer
@SpringJUnitConfig(initializers = BaseInitializer.class) (1)
class BaseTest {
	// class body...
}

// ApplicationContext will be initialized by BaseInitializer
// and ExtendedInitializer
@SpringJUnitConfig(initializers = ExtendedInitializer.class) (2)
class ExtendedTest extends BaseTest {
	// class body...
}
1 Initializer defined in the superclass.
2 Initializer defined in the subclass.
Kotlin
// ApplicationContext will be initialized by BaseInitializer
@SpringJUnitConfig(initializers = [BaseInitializer::class]) (1)
open class BaseTest {
	// class body...
}

// ApplicationContext will be initialized by BaseInitializer
// and ExtendedInitializer
@SpringJUnitConfig(initializers = [ExtendedInitializer::class]) (2)
class ExtendedTest : BaseTest() {
	// class body...
}
3 Initializer defined in the superclass.
4 Initializer defined in the subclass.