テスト用のメタアノテーションのサポート

ほとんどのテスト関連のアノテーションをメタアノテーションとして使用して、カスタム合成アノテーションを作成し、テストスイート全体での構成の重複を減らすことができます。

次のそれぞれを TestContext フレームワークと組み合わせてメタアノテーションとして使用できます。

  • @BootstrapWith

  • @ContextConfiguration

  • @ContextHierarchy

  • @ContextCustomizerFactories

  • @ActiveProfiles

  • @TestPropertySource

  • @DirtiesContext

  • @WebAppConfiguration

  • @TestExecutionListeners

  • @Transactional

  • @BeforeTransaction

  • @AfterTransaction

  • @Commit

  • @Rollback

  • @Sql

  • @SqlConfig

  • @SqlMergeMode

  • @SqlGroup

  • @Repeat (JUnit 4 でのみサポート)

  • @Timed (JUnit 4 でのみサポート)

  • @IfProfileValue (JUnit 4 でのみサポート)

  • @ProfileValueSourceConfiguration (JUnit 4 でのみサポート)

  • @SpringJUnitConfig (JUnit Jupiter でのみサポート)

  • @SpringJUnitWebConfig (JUnit Jupiter でのみサポート)

  • @TestConstructor (JUnit Jupiter でのみサポート)

  • @NestedTestConfiguration (JUnit Jupiter でのみサポート)

  • @EnabledIf (JUnit Jupiter でのみサポート)

  • @DisabledIf (JUnit Jupiter でのみサポート)

次の例を考えてみましょう。

  • Java

  • Kotlin

@RunWith(SpringRunner.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public class OrderRepositoryTests { }

@RunWith(SpringRunner.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public class UserRepositoryTests { }
@RunWith(SpringRunner::class)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
class OrderRepositoryTests { }

@RunWith(SpringRunner::class)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
class UserRepositoryTests { }

JUnit 4 ベースのテストスイート全体で上記の構成を繰り返していることがわかった場合は、次のように、Spring の共通のテスト構成を集中化するカスタム合成アノテーションを導入することで、重複を減らすことができます。

  • Java

  • Kotlin

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public @interface TransactionalDevTestConfig { }
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
annotation class TransactionalDevTestConfig { }

次に、次のように、カスタム @TransactionalDevTestConfig アノテーションを使用して、個々の JUnit 4 ベースのテストクラスの構成を簡素化できます。

  • Java

  • Kotlin

@RunWith(SpringRunner.class)
@TransactionalDevTestConfig
public class OrderRepositoryTests { }

@RunWith(SpringRunner.class)
@TransactionalDevTestConfig
public class UserRepositoryTests { }
@RunWith(SpringRunner::class)
@TransactionalDevTestConfig
class OrderRepositoryTests

@RunWith(SpringRunner::class)
@TransactionalDevTestConfig
class UserRepositoryTests

JUnit Jupiter を使用するテストを記述する場合、JUnit 5 のアノテーションもメタアノテーションとして使用できるため、コードの重複をさらに減らすことができます。次の例を考えてみましょう。

  • Java

  • Kotlin

@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
class OrderRepositoryTests { }

@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
class UserRepositoryTests { }
@ExtendWith(SpringExtension::class)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
class OrderRepositoryTests { }

@ExtendWith(SpringExtension::class)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
class UserRepositoryTests { }

JUnit Jupiter ベースのテストスイート全体で上記の構成を繰り返していることがわかった場合、次のように、Spring と JUnit Jupiter の共通のテスト構成を集中化するカスタム構成アノテーションを導入することで、重複を減らすことができます。

  • Java

  • Kotlin

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public @interface TransactionalDevTestConfig { }
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
@ExtendWith(SpringExtension::class)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
annotation class TransactionalDevTestConfig { }

次に、次のように、カスタム @TransactionalDevTestConfig アノテーションを使用して、個々の JUnit Jupiter ベースのテストクラスの構成を簡素化できます。

  • Java

  • Kotlin

@TransactionalDevTestConfig
class OrderRepositoryTests { }

@TransactionalDevTestConfig
class UserRepositoryTests { }
@TransactionalDevTestConfig
class OrderRepositoryTests { }

@TransactionalDevTestConfig
class UserRepositoryTests { }

JUnit Jupiter は @Test@RepeatedTestParameterizedTest などのメタアノテーションとしての使用をサポートしているため、テストメソッドレベルでカスタム合成アノテーションを作成することもできます。例: JUnit Jupiter の @Test アノテーションと @Tag アノテーションを Spring の @Transactional アノテーションと組み合わせる合成アノテーションを作成する場合、次のように @TransactionalIntegrationTest アノテーションを作成できます。

  • Java

  • Kotlin

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Transactional
@Tag("integration-test") // org.junit.jupiter.api.Tag
@Test // org.junit.jupiter.api.Test
public @interface TransactionalIntegrationTest { }
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
@Transactional
@Tag("integration-test") // org.junit.jupiter.api.Tag
@Test // org.junit.jupiter.api.Test
annotation class TransactionalIntegrationTest { }

次に、カスタム @TransactionalIntegrationTest アノテーションを使用して、次のように、個々の JUnit Jupiter ベースのテストメソッドの構成を簡素化できます。

  • Java

  • Kotlin

@TransactionalIntegrationTest
void saveOrder() { }

@TransactionalIntegrationTest
void deleteOrder() { }
@TransactionalIntegrationTest
fun saveOrder() { }

@TransactionalIntegrationTest
fun deleteOrder() { }

詳細については、Spring アノテーションプログラミングモデル [GitHub] (英語) wiki ページを参照してください。