コンテキストの階層

ロードされた Spring ApplicationContext に依存する統合テストを作成する場合、多くの場合、単一のコンテキストに対してテストするだけで十分です。ただし、ApplicationContext インスタンスの階層に対してテストすることが有益な場合や、必要な場合もあります。例: Spring MVC Web アプリケーションを開発している場合、通常、ルート WebApplicationContext は Spring の ContextLoaderListener によってロードされ、子 WebApplicationContext は Spring の DispatcherServlet によってロードされます。これにより、共有コンポーネントとインフラストラクチャ構成がルートコンテキストで宣言され、Web 固有のコンポーネントによって子コンテキストで使用される親子コンテキスト階層が作成されます。Spring Batch アプリケーションには別の使用例があり、多くの場合、共有バッチインフラストラクチャの構成を提供する親コンテキストと、特定のバッチジョブの構成用の子コンテキストがあります。

個々のテストクラスまたはテストクラス階層内で、@ContextHierarchy アノテーションを使用してコンテキスト構成を宣言することにより、コンテキスト階層を使用する統合テストを作成できます。テストクラス階層内の複数のクラスでコンテキスト階層が宣言されている場合、コンテキスト階層の特定の名前付きレベルのコンテキスト構成をマージまたはオーバーライドすることもできます。階層内の特定のレベルの構成をマージする場合、構成リソース型(つまり、XML 構成ファイルまたはコンポーネントクラス)は一貫している必要があります。それ以外の場合、異なるリソース型を使用して設定されたコンテキスト階層の異なるレベルを持つことは完全に受け入れられます。

このセクションの残りの JUnit Jupiter ベースの例は、コンテキスト階層の使用を必要とする統合テストの一般的な構成シナリオを示しています。

コンテキスト階層を持つ単一のテストクラス

ControllerIntegrationTests は、ルート WebApplicationContext (TestAppConfig@Configuration クラスを使用してロード)とディスパッチャーサーブレット WebApplicationContext (WebConfig を使用してロード)の 2 つのレベルで構成されるコンテキスト階層を宣言することにより、Spring MVC Web アプリケーションの一般的な統合テストシナリオを表します。@Configuration クラス)。テストインスタンスにオートワイヤーされる WebApplicationContext は、子コンテキスト(つまり、階層内の最下位のコンテキスト)用のものです。次のリストは、この構成シナリオを示しています。

  • Java

  • Kotlin

@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextHierarchy({
	@ContextConfiguration(classes = TestAppConfig.class),
	@ContextConfiguration(classes = WebConfig.class)
})
class ControllerIntegrationTests {

	@Autowired
	WebApplicationContext wac;

	// ...
}
@ExtendWith(SpringExtension::class)
@WebAppConfiguration
@ContextHierarchy(
	ContextConfiguration(classes = [TestAppConfig::class]),
	ContextConfiguration(classes = [WebConfig::class]))
class ControllerIntegrationTests {

	@Autowired
	lateinit var wac: WebApplicationContext

	// ...
}

暗黙的な親コンテキストを持つクラス階層

この例のテストクラスは、テストクラス階層内のコンテキスト階層を定義します。AbstractWebTests は、Spring を使用した Web アプリケーションでルート WebApplicationContext の構成を宣言します。ただし、AbstractWebTests は @ContextHierarchy を宣言しないことに注意してください。AbstractWebTests のサブクラスは、オプションでコンテキスト階層に参加したり、@ContextConfiguration の標準的なセマンティクスに従うことができます。SoapWebServiceTests と RestWebServiceTests は両方とも AbstractWebTests を継承し、@ContextHierarchy を使用してコンテキスト階層を定義します。その結果、3 つのアプリケーションコンテキスト(@ContextConfiguration の宣言ごとに 1 つ)が読み込まれ、AbstractWebTests の構成に基づいて読み込まれたアプリケーションコンテキストが、具象サブクラスに読み込まれた各コンテキストの親コンテキストとして設定されます。次のリストは、この構成シナリオを示しています。

  • Java

  • Kotlin

@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
public abstract class AbstractWebTests {}

@ContextHierarchy(@ContextConfiguration("/spring/soap-ws-config.xml"))
public class SoapWebServiceTests extends AbstractWebTests {}

@ContextHierarchy(@ContextConfiguration("/spring/rest-ws-config.xml"))
public class RestWebServiceTests extends AbstractWebTests {}
@ExtendWith(SpringExtension::class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
abstract class AbstractWebTests

@ContextHierarchy(ContextConfiguration("/spring/soap-ws-config.xml"))
class SoapWebServiceTests : AbstractWebTests()

@ContextHierarchy(ContextConfiguration("/spring/rest-ws-config.xml"))
class RestWebServiceTests : AbstractWebTests()

コンテキスト階層構成がマージされたクラス階層

この例のクラスは、コンテキスト階層内の特定のレベルの構成をマージするための名前付き階層レベルの使用を示しています。BaseTests は、階層内の 2 つのレベル、parent および child を定義します。ExtendedTests は BaseTests を継承し、@ContextConfiguration の name 属性で宣言された名前が両方とも child であることを確認することにより、child 階層レベルのコンテキスト構成をマージするように Spring TestContext フレームワークに指示します。その結果、/app-config.xml 用、/user-config.xml 用、{"/user-config.xml", "/order-config.xml"} 用の 3 つのアプリケーションコンテキストがロードされます。前の例と同様に、/app-config.xml からロードされたアプリケーションコンテキストは、/user-config.xml および {"/user-config.xml", "/order-config.xml"} からロードされたコンテキストの親コンテキストとして設定されます。次のリストは、この構成シナリオを示しています。

  • Java

  • Kotlin

@ExtendWith(SpringExtension.class)
@ContextHierarchy({
	@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
	@ContextConfiguration(name = "child", locations = "/user-config.xml")
})
class BaseTests {}

@ContextHierarchy(
	@ContextConfiguration(name = "child", locations = "/order-config.xml")
)
class ExtendedTests extends BaseTests {}
@ExtendWith(SpringExtension::class)
@ContextHierarchy(
	ContextConfiguration(name = "parent", locations = ["/app-config.xml"]),
	ContextConfiguration(name = "child", locations = ["/user-config.xml"]))
open class BaseTests {}

@ContextHierarchy(
	ContextConfiguration(name = "child", locations = ["/order-config.xml"])
)
class ExtendedTests : BaseTests() {}

オーバーライドされたコンテキスト階層構成を持つクラス階層

前の例とは対照的に、この例は、@ContextConfiguration の inheritLocations フラグを false に設定することにより、コンテキスト階層内の特定の名前付きレベルの構成をオーバーライドする方法を示しています。その結果、ExtendedTests のアプリケーションコンテキストは /test-user-config.xml からのみロードされ、/app-config.xml からロードされたコンテキストに親が設定されます。次のリストは、この構成シナリオを示しています。

  • Java

  • Kotlin

@ExtendWith(SpringExtension.class)
@ContextHierarchy({
	@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
	@ContextConfiguration(name = "child", locations = "/user-config.xml")
})
class BaseTests {}

@ContextHierarchy(
	@ContextConfiguration(
		name = "child",
		locations = "/test-user-config.xml",
		inheritLocations = false
))
class ExtendedTests extends BaseTests {}
@ExtendWith(SpringExtension::class)
@ContextHierarchy(
	ContextConfiguration(name = "parent", locations = ["/app-config.xml"]),
	ContextConfiguration(name = "child", locations = ["/user-config.xml"]))
open class BaseTests {}

@ContextHierarchy(
		ContextConfiguration(
				name = "child",
				locations = ["/test-user-config.xml"],
				inheritLocations = false
		))
class ExtendedTests : BaseTests() {}
コンテキスト階層内のコンテキストを汚す
コンテキストがコンテキスト階層の一部として構成されているテストで @DirtiesContext を使用する場合、hierarchyMode フラグを使用してコンテキストキャッシュをクリアする方法を制御できます。詳細については、Spring Test アノテーションの @DirtiesContext および @DirtiesContext javadoc の説明を参照してください。