你可以使用大多数与测试相关的注解作为 元注解 来创建自定义的组合注解,并减少整个测试套件的配置重复。

    你可以结合 TestContext 框架使用以下每个元注解:

    • @BootstrapWith
    • @ContextConfiguration
    • @ContextHierarchy
    • @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 上支持)

    请考虑以下例子:

    1. @RunWith(SpringRunner.class)
    2. @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
    3. @ActiveProfiles("dev")
    4. @Transactional
    5. public class OrderRepositoryTests { }
    6. @RunWith(SpringRunner.class)
    7. @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
    8. @ActiveProfiles("dev")
    9. @Transactional
    10. public class UserRepositoryTests { }

    如果我们发现我们在整个基于 JUnit 4 的测试套件中重复前面的配置,我们可以通过引入一个自定义的组合注解来减少重复,该注解集中了 Spring 的通用测试配置,如下所示:

    1. @Target(ElementType.TYPE)
    2. @Retention(RetentionPolicy.RUNTIME)
    3. @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
    4. @ActiveProfiles("dev")
    5. @Transactional
    6. public @interface TransactionalDevTestConfig { }

    然后我们可以使用我们自定义的 @TransactionalDevTestConfig注解来简化基于 JUnit 4 的各个测试类的配置,如下所示:

    1. @RunWith(SpringRunner.class)
    2. @TransactionalDevTestConfig
    3. public class OrderRepositoryTests { }
    4. @RunWith(SpringRunner.class)
    5. @TransactionalDevTestConfig
    6. public class UserRepositoryTests { }

    如果我们编写使用 JUnit Jupiter 的测试,我们可以进一步减少代码重复,因为 JUnit 5 中的注解也可以作为元注解使用。考虑一下下面的例子:

    1. @ExtendWith(SpringExtension.class)
    2. @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
    3. @ActiveProfiles("dev")
    4. @Transactional
    5. class OrderRepositoryTests { }
    6. @ExtendWith(SpringExtension.class)
    7. @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
    8. @ActiveProfiles("dev")
    9. @Transactional
    10. class UserRepositoryTests { }

    如果我们发现我们在基于 JUnit Jupiter 的测试套件中重复了前面的配置,我们可以通过引入一个自定义的组合注解来减少重复,该注解集中了Spring 和 JUnit Jupiter 的通用测试配置,如下所示:

    1. @Target(ElementType.TYPE)
    2. @Retention(RetentionPolicy.RUNTIME)
    3. @ExtendWith(SpringExtension.class)
    4. @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
    5. @ActiveProfiles("dev")
    6. @Transactional
    7. public @interface TransactionalDevTestConfig { }

    然后我们可以使用我们自定义的 @TransactionalDevTestConfig注解来简化基于 JUnit Jupiter 的各个测试类的配置,如下所示:

    1. @TransactionalDevTestConfig
    2. class OrderRepositoryTests { }
    3. @TransactionalDevTestConfig
    4. class UserRepositoryTests { }

    由于 JUnit Jupiter 支持使用 @Test@RepeatedTestParameterizedTest等作为元注解,你也可以在测试方法级别创建自定义的组成注解。例如,如果我们希望创建一个组合注解,将 JUnit Jupiter 的 @Test@Tag注解与 Spring 的 @Transactional注解相结合,我们可以创建一个 @TransactionalIntegrationTest注解,如下所示:

    1. @Target(ElementType.METHOD)
    2. @Retention(RetentionPolicy.RUNTIME)
    3. @Transactional
    4. @Tag("integration-test") // org.junit.jupiter.api.Tag
    5. @Test // org.junit.jupiter.api.Test
    6. public @interface TransactionalIntegrationTest { }

    然后我们可以使用我们自定义的 @TransactionalIntegrationTest注解来简化基于 JUnit Jupiter 的各个测试方法的配置,如下所示:

    1. @TransactionalIntegrationTest
    2. void saveOrder() { }
    3. @TransactionalIntegrationTest
    4. void deleteOrder() { }

    更多细节,请参见 Spring 注解编程模型维基页面