TestContext フレームワークサポートクラス

このセクションでは、Spring TestContext フレームワークをサポートするさまざまなクラスについて説明します。

Spring JUnit 4 ランナー

Spring TestContext フレームワークは、カスタムランナー(JUnit 4.12 以上でサポート)を介して JUnit 4 と完全に統合されています。テストクラスに @RunWith(SpringJUnit4ClassRunner.class) または短い @RunWith(SpringRunner.class) バリアントをアノテーションすることにより、開発者は標準の JUnit 4 ベースのユニットおよび統合テストを実装し、同時にアプリケーションコンテキストのロードのサポート、テストインスタンスの依存性注入、トランザクションテストなど、TestContext フレームワークの利点を享受できます。メソッドの実行など。Spring TestContext フレームワークを代替ランナー(JUnit 4 の Parameterized ランナーなど)またはサードパーティランナー(MockitoJUnitRunner など)で使用する場合は、オプションで Spring の JUnit ルールのサポートを代わりに使用できます。

次のコードリストは、テストクラスをカスタム Spring Runner で実行するように構成するための最小要件を示しています。

  • Java

  • Kotlin

@RunWith(SpringRunner.class)
@TestExecutionListeners({})
public class SimpleTest {

	@Test
	public void testMethod() {
		// test logic...
	}
}
@RunWith(SpringRunner::class)
@TestExecutionListeners
class SimpleTest {

	@Test
	fun testMethod() {
		// test logic...
	}
}

上記の例では、@TestExecutionListeners が空のリストで構成され、デフォルトのリスナーを無効にします。そうしないと、ApplicationContext を @ContextConfiguration で構成する必要があります。

Spring JUnit 4 ルール

org.springframework.test.context.junit4.rules パッケージは、次の JUnit 4 ルールを提供します(JUnit 4.12 以降でサポートされます)。

  • SpringClassRule

  • SpringMethodRule

SpringClassRule は Spring TestContext フレームワークのクラスレベルの機能をサポートする JUnit TestRule であり、SpringMethodRule は Spring TestContext フレームワークのインスタンスレベルおよびメソッドレベルの機能をサポートする JUnit MethodRule です。

SpringRunner とは対照的に、Spring のルールベースの JUnit サポートには、org.junit.runner.Runner の実装に依存しないという利点があるため、既存の代替ランナー(JUnit 4 の Parameterized など)またはサードパーティランナー(MockitoJUnitRunner など)と組み合わせることができます)。

TestContext フレームワークのすべての機能をサポートするには、SpringClassRule と SpringMethodRule を組み合わせる必要があります。次の例は、統合テストでこれらのルールを宣言する適切な方法を示しています。

  • Java

  • Kotlin

// Optionally specify a non-Spring Runner via @RunWith(...)
@ContextConfiguration
public class IntegrationTest {

	@ClassRule
	public static final SpringClassRule springClassRule = new SpringClassRule();

	@Rule
	public final SpringMethodRule springMethodRule = new SpringMethodRule();

	@Test
	public void testMethod() {
		// test logic...
	}
}
// Optionally specify a non-Spring Runner via @RunWith(...)
@ContextConfiguration
class IntegrationTest {

	@Rule
	val springMethodRule = SpringMethodRule()

	@Test
	fun testMethod() {
		// test logic...
	}

	companion object {
		@ClassRule
		val springClassRule = SpringClassRule()
	}
}

JUnit 4 サポートクラス

org.springframework.test.context.junit4 パッケージは、JUnit 4 ベースのテストケースに次のサポートクラスを提供します(JUnit 4.12 以上でサポートされます)。

  • AbstractJUnit4SpringContextTests

  • AbstractTransactionalJUnit4SpringContextTests

AbstractJUnit4SpringContextTests は、Spring TestContext フレームワークを JUnit4 環境での明示的な ApplicationContext テストサポートと統合する抽象基本テストクラスです。AbstractJUnit4SpringContextTests を継承すると、protectedapplicationContext インスタンス変数にアクセスできます。この変数を使用して、明示的な Bean ルックアップを実行したり、コンテキスト全体の状態をテストしたりできます。

AbstractTransactionalJUnit4SpringContextTests は、AbstractJUnit4SpringContextTests の抽象的なトランザクション拡張であり、JDBC アクセスにいくつかの便利な機能を追加します。このクラスは、javax.sql.DataSource Bean および PlatformTransactionManager Bean が ApplicationContext で定義されていることを想定しています。AbstractTransactionalJUnit4SpringContextTests を継承すると、SQL ステートメントを実行してデータベースを照会するために使用できる protectedjdbcTemplate インスタンス変数にアクセスできます。このようなクエリを使用して、データベース関連のアプリケーションコードを実行する前後の両方でデータベースの状態を確認できます。Spring は、このようなクエリがアプリケーションコードと同じトランザクションのスコープで実行されることを保証します。ORM ツールと組み合わせて使用する場合は、検知を避けてください。JDBC テストのサポートで説明したように、AbstractTransactionalJUnit4SpringContextTests は、前述の jdbcTemplate を使用して JdbcTestUtils のメソッドに委譲する便利なメソッドも提供します。さらに、AbstractTransactionalJUnit4SpringContextTests は、構成された DataSource に対して SQL スクリプトを実行するための executeSqlScript(..) メソッドを提供します。

これらのクラスは拡張に便利です。テストクラスを Spring 固有のクラス階層に結び付けたくない場合は、@RunWith(SpringRunner.class) または Spring の JUnit ルールを使用して独自のカスタムテストクラスを構成できます。

JUnit Jupiter 用 SpringExtension

Spring TestContext フレームワークは、JUnit 5 で導入された JUnit Jupiter テストフレームワークとの完全な統合を提供します。@ExtendWith(SpringExtension.class) でテストクラスにアノテーションを付けることで、標準の JUnit Jupiter ベースのユニットテストと統合テストを実装し、同時に TestContext フレームワークのメリットを享受できます。アプリケーションコンテキストのロード、テストインスタンスの依存性注入、トランザクションテストメソッドの実行などのサポート。

さらに、JUnit Jupiter の豊富な拡張 API のおかげで、Spring は、Spring が JUnit 4 および TestNG に対してサポートする機能セットに加えて、以下の機能を提供します。

次のコードリストは、SpringExtension を @ContextConfiguration と組み合わせて使用するようにテストクラスを構成する方法を示しています。

  • Java

  • Kotlin

// Instructs JUnit Jupiter to extend the test with Spring support.
@ExtendWith(SpringExtension.class)
// Instructs Spring to load an ApplicationContext from TestConfig.class
@ContextConfiguration(classes = TestConfig.class)
class SimpleTests {

	@Test
	void testMethod() {
		// test logic...
	}
}
// Instructs JUnit Jupiter to extend the test with Spring support.
@ExtendWith(SpringExtension::class)
// Instructs Spring to load an ApplicationContext from TestConfig::class
@ContextConfiguration(classes = [TestConfig::class])
class SimpleTests {

	@Test
	fun testMethod() {
		// test logic...
	}
}

JUnit 5 のアノテーションもメタアノテーションとして使用できるため、Spring は @SpringJUnitConfig および @SpringJUnitWebConfig 構成アノテーションを提供して、テスト ApplicationContext および JUnit Jupiter の構成を簡素化します。

次の例では、@SpringJUnitConfig を使用して、前の例で使用した構成の量を削減します。

  • Java

  • Kotlin

// Instructs Spring to register the SpringExtension with JUnit
// Jupiter and load an ApplicationContext from TestConfig.class
@SpringJUnitConfig(TestConfig.class)
class SimpleTests {

	@Test
	void testMethod() {
		// test logic...
	}
}
// Instructs Spring to register the SpringExtension with JUnit
// Jupiter and load an ApplicationContext from TestConfig.class
@SpringJUnitConfig(TestConfig::class)
class SimpleTests {

	@Test
	fun testMethod() {
		// test logic...
	}
}

同様に、次の例では、@SpringJUnitWebConfig を使用して、JUnit Jupiter で使用する WebApplicationContext を作成します。

  • Java

  • Kotlin

// Instructs Spring to register the SpringExtension with JUnit
// Jupiter and load a WebApplicationContext from TestWebConfig.class
@SpringJUnitWebConfig(TestWebConfig.class)
class SimpleWebTests {

	@Test
	void testMethod() {
		// test logic...
	}
}
// Instructs Spring to register the SpringExtension with JUnit
// Jupiter and load a WebApplicationContext from TestWebConfig::class
@SpringJUnitWebConfig(TestWebConfig::class)
class SimpleWebTests {

	@Test
	fun testMethod() {
		// test logic...
	}
}

詳細については、Spring JUnit Jupiter テストアノテーションの @SpringJUnitConfig および @SpringJUnitWebConfig の資料を参照してください。

SpringExtension による依存関係の注入

SpringExtension は、JUnit Jupiter の ParameterResolver (英語) 拡張 API を実装します。これにより、Spring は、テストコンストラクター、テストメソッド、テストライフサイクルコールバックメソッドに依存関係の注入を提供できます。

具体的には、SpringExtension は、テストの ApplicationContext からの依存関係を、Spring の @BeforeTransaction および @AfterTransaction または JUnit の @BeforeAll@AfterAll@BeforeEach@AfterEach@Test@RepeatedTest@ParameterizedTest などでアノテーションが付けられたテストコンストラクターおよびメソッドに注入できます。

コンストラクターインジェクション

JUnit Jupiter テストクラスのコンストラクター内の特定のパラメーターが型 ApplicationContext (またはそのサブ型)であるか、@Autowired@Qualifier@Value でアノテーションが付けられているかメタアノテーションが付けられている場合、Spring はその特定のパラメーターの値に対応する Bean またはテストの ApplicationContext からの値。

Spring は、コンストラクターが autowirable であると見なされる場合、テストクラスコンストラクターのすべての引数をオートワイヤーするように構成することもできます。コンストラクターは、次の条件のいずれかが(優先順位の順に)満たされる場合、自動書き込み可能と見なされます。

  • コンストラクターには @Autowired のアノテーションが付けられます。

  • @TestConstructor は、autowireMode 属性が ALL に設定されたテストクラスに存在またはメタ存在します。

  • デフォルトのテストコンストラクターのオートワイヤーモードは ALL に変更されました。

@TestConstructor の使用と、グローバルテストコンストラクターのオートワイヤーモードを変更する方法の詳細については、@TestConstructor を参照してください

テストクラスのコンストラクターが autowirable であると見なされる場合、Spring はコンストラクター内のすべてのパラメーターの引数を解決する責任を負います。その結果、JUnit Jupiter に登録されている他の ParameterResolver は、そのようなコンストラクターのパラメーターを解決できません。

@DirtiesContext を使用してテストメソッドの前または後にテストの ApplicationContext を閉じる場合、テストクラスのコンストラクターインジェクションを JUnit Jupiter の @TestInstance(PER_CLASS) サポートと組み合わせて使用しないでください。

その理由は、@TestInstance(PER_CLASS) が JUnit Jupiter にテストメソッドの呼び出しの間にテストインスタンスをキャッシュするように指示するためです。その結果、テストインスタンスは、その後閉じられた ApplicationContext から最初に注入された Bean への参照を保持します。このようなシナリオではテストクラスのコンストラクターが 1 回だけ呼び出されるため、依存関係の注入は再度行われず、後続のテストは閉じられた ApplicationContext の Bean と対話し、エラーが発生する可能性があります。

@TestInstance(PER_CLASS) と組み合わせて @DirtiesContext を「テストメソッド前」または「テストメソッド後」モードで使用するには、Spring からの依存関係をフィールドまたは setter インジェクションを介して提供し、テストメソッド呼び出しの間に再インジェクトできるように構成する必要があります。

次の例では、Spring は、TestConfig.class から OrderServiceIntegrationTests コンストラクターにロードされた ApplicationContext から OrderService Bean を注入します。

  • Java

  • Kotlin

@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {

	private final OrderService orderService;

	@Autowired
	OrderServiceIntegrationTests(OrderService orderService) {
		this.orderService = orderService;
	}

	// tests that use the injected OrderService
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests @Autowired constructor(private val orderService: OrderService){
	// tests that use the injected OrderService
}

この機能により、テストの依存関係が final になり、不変になります。

spring.test.constructor.autowire.mode プロパティが all の場合(@TestConstructor を参照)、前の例のコンストラクターでの @Autowired の宣言を省略して、次のようにすることができます。

  • Java

  • Kotlin

@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {

	private final OrderService orderService;

	OrderServiceIntegrationTests(OrderService orderService) {
		this.orderService = orderService;
	}

	// tests that use the injected OrderService
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests(val orderService:OrderService) {
	// tests that use the injected OrderService
}

メソッドインジェクション

JUnit Jupiter テストメソッドまたはテストライフサイクルコールバックメソッドのパラメーターが型 ApplicationContext (またはそのサブ型)であるか、@Autowired@Qualifier@Value でアノテーションが付けられているかメタアノテーションが付けられている場合、Spring はその特定のパラメーターの値をテストの ApplicationContext からの対応する Bean。

次の例では、Spring は TestConfig.class から deleteOrder() テストメソッドにロードされた ApplicationContext から OrderService を挿入します。

  • Java

  • Kotlin

@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {

	@Test
	void deleteOrder(@Autowired OrderService orderService) {
		// use orderService from the test's ApplicationContext
	}
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests {

	@Test
	fun deleteOrder(@Autowired orderService: OrderService) {
		// use orderService from the test's ApplicationContext
	}
}

JUnit Jupiter の ParameterResolver サポートの堅牢性により、Spring だけでなく、JUnit Jupiter 自体または他のサードパーティの拡張機能からも、単一のメソッドに複数の依存関係を注入できます。

次の例は、Spring と JUnit Jupiter の両方で placeOrderRepeatedly() テストメソッドに依存関係を同時に注入するメソッドを示しています。

  • Java

  • Kotlin

@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {

	@RepeatedTest(10)
	void placeOrderRepeatedly(RepetitionInfo repetitionInfo,
			@Autowired OrderService orderService) {

		// use orderService from the test's ApplicationContext
		// and repetitionInfo from JUnit Jupiter
	}
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests {

	@RepeatedTest(10)
	fun placeOrderRepeatedly(repetitionInfo:RepetitionInfo, @Autowired orderService:OrderService) {

		// use orderService from the test's ApplicationContext
		// and repetitionInfo from JUnit Jupiter
	}
}

JUnit Jupiter の @RepeatedTest を使用すると、テストメソッドが RepetitionInfo にアクセスできることに注意してください。

@Nested テストクラスの構成

Spring TestContext フレームワークは、Spring Framework 5.0 以降、JUnit Jupiter の @Nested テストクラスでのテスト関連のアノテーションの使用をサポートしています。ただし、Spring Framework 5.3 クラスレベルのテスト構成アノテーションが、スーパークラスからのようにクラスを囲むことから継承される

Spring Framework 5.3 では、周囲のクラスからテストクラス構成を継承するためのファーストクラスのサポートが導入され、そのような構成はデフォルトで継承されます。デフォルトの INHERIT モードから OVERRIDE モードに変更するには、個々の @Nested テストクラスに @NestedTestConfiguration(EnclosingConfiguration.OVERRIDE) のアノテーションを付けることができます。明示的な @NestedTestConfiguration 宣言は、アノテーション付きのテストクラスだけでなく、そのサブクラスやネストされたクラスにも適用されます。トップレベルのテストクラスに @NestedTestConfiguration のアノテーションを付けると、そのすべてのネストされたテストクラスに再帰的に適用されます。

開発チームがデフォルトを OVERRIDE に変更できるようにするために(たとえば、Spring Framework 5.0 から 5.2 との互換性のために)、デフォルトモードは、JVM システムプロパティまたはクラスパスのルートにある spring.properties ファイルを介してグローバルに変更できます。詳細については、「デフォルトの包含構成継承モードの変更」ノートを参照してください。

次の "Hello World" の例は非常に単純化されていますが、@Nested テストクラスによって継承される最上位クラスで共通の構成を宣言する方法を示しています。この特定の例では、TestConfig 構成クラスのみが継承されます。ネストされた各テストクラスは、独自のアクティブなプロファイルのセットを提供し、ネストされた各テストクラスに個別の ApplicationContext を提供します (詳細については、コンテキストキャッシングを参照してください)。サポートされているアノテーションのリストを参照して、@Nested テストクラスで継承できるアノテーションを確認してください。

  • Java

  • Kotlin

@SpringJUnitConfig(TestConfig.class)
class GreetingServiceTests {

	@Nested
	@ActiveProfiles("lang_en")
	class EnglishGreetings {

		@Test
		void hello(@Autowired GreetingService service) {
			assertThat(service.greetWorld()).isEqualTo("Hello World");
		}
	}

	@Nested
	@ActiveProfiles("lang_de")
	class GermanGreetings {

		@Test
		void hello(@Autowired GreetingService service) {
			assertThat(service.greetWorld()).isEqualTo("Hallo Welt");
		}
	}
}
@SpringJUnitConfig(TestConfig::class)
class GreetingServiceTests {

	@Nested
	@ActiveProfiles("lang_en")
	inner class EnglishGreetings {

		@Test
		fun hello(@Autowired service:GreetingService) {
			assertThat(service.greetWorld()).isEqualTo("Hello World")
		}
	}

	@Nested
	@ActiveProfiles("lang_de")
	inner class GermanGreetings {

		@Test
		fun hello(@Autowired service:GreetingService) {
			assertThat(service.greetWorld()).isEqualTo("Hallo Welt")
		}
	}
}

TestNG サポートクラス

org.springframework.test.context.testng パッケージは、TestNG ベースのテストケースに対して以下のサポートクラスを提供します。

  • AbstractTestNGSpringContextTests

  • AbstractTransactionalTestNGSpringContextTests

AbstractTestNGSpringContextTests は、Spring TestContext フレームワークを TestNG 環境での明示的な ApplicationContext テストサポートと統合する抽象基本テストクラスです。AbstractTestNGSpringContextTests を継承すると、protectedapplicationContext インスタンス変数にアクセスできます。この変数を使用して、明示的な Bean ルックアップを実行したり、コンテキスト全体の状態をテストしたりできます。

AbstractTransactionalTestNGSpringContextTests は、AbstractTestNGSpringContextTests の抽象的なトランザクション拡張であり、JDBC アクセスにいくつかの便利な機能を追加します。このクラスは、javax.sql.DataSource Bean および PlatformTransactionManager Bean が ApplicationContext で定義されていることを想定しています。AbstractTransactionalTestNGSpringContextTests を継承すると、SQL ステートメントを実行してデータベースを照会するために使用できる protectedjdbcTemplate インスタンス変数にアクセスできます。このようなクエリを使用して、データベース関連のアプリケーションコードを実行する前後の両方でデータベースの状態を確認できます。Spring は、このようなクエリがアプリケーションコードと同じトランザクションのスコープで実行されることを保証します。ORM ツールと組み合わせて使用する場合は、検知を避けてください。JDBC テストのサポートで説明したように、AbstractTransactionalTestNGSpringContextTests は、前述の jdbcTemplate を使用して JdbcTestUtils のメソッドに委譲する便利なメソッドも提供します。さらに、AbstractTransactionalTestNGSpringContextTests は、構成された DataSource に対して SQL スクリプトを実行するための executeSqlScript(..) メソッドを提供します。

これらのクラスは拡張に便利です。テストクラスを Spring 固有のクラス階層に関連付けたくない場合は、@ContextConfiguration@TestExecutionListeners などを使用し、テストクラスを TestContextManager で手動でインストルメント化することにより、独自のカスタムテストクラスを構成できます。テストクラスをインストルメント化する方法の例については、AbstractTestNGSpringContextTests のソースコードを参照してください。