为多组不同的配置文件测试一个Spring测试类

4

我正在使用:

  • Spring框架4.3.10
  • JUnit4.12
  • Gradle4.3.1

我有这两个测试类:

@Transactional
@RunWith(Parameterized.class)
@ContextConfiguration(classes={RootApplicationContext.class})
@ActiveProfiles(resolver=TestJdbcActiveProfilesResolver.class)
@TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public class PersonaServiceImplJdbcTest {


@Transactional
@RunWith(Parameterized.class)
@ContextConfiguration(classes={RootApplicationContext.class})
@ActiveProfiles(resolver=TestHibernateActiveProfilesResolver.class)
@TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public class PersonaServiceImplHibernateTest {

关于 @Test 方法的代码在两个测试类中是相同的,这违反了 DRY 原则。这两个测试类之间唯一的区别在于 jdbcHibernate 配置文件与其他配置文件(例如 development, mysql)一起使用,它们内部通过每个 TestXXXActiveProfilesResolver 类的变化来实现。
到目前为止,我有 2 个测试类,违反了 DRY 原则,如果按层次思考,我将得到 3 个测试类。
如何(如果可能)使用一个测试类,在每个交互中执行两个(或更多)设置文件,例如:
  • jdbc,development,mysql
  • Hibernate,development,mysql
我已经阅读了以下内容: 但我想避免使用命令,无论是通过 Maven 还是 Gradle,而是通过 TestXXXActiveProfilesResolver 类来保持控制。

如果你只是想分享测试方法的代码,可以创建一个它们都引用的委托,或者添加一个包含共享代码的公共基类。 - Taylor
我对继承的层次结构也有同样的看法,但是我考虑了以下内容:https://www.petrikainulainen.net/programming/unit-testing/3-reasons-why-we-should-not-use-inheritance-in-our-tests/ - Manuel Jordan
好的,使用组合代替。 - Taylor
1个回答

5

对于 JUnit 4,最终我采取了以下步骤(向下滚动):

@Transactional
@RunWith(Parameterized.class)
@ContextConfiguration(classes={RootApplicationContext.class})
//@ActiveProfiles() ... disable
@TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public abstract class PersonaServiceImplTest {

   ...

   @Autowired
   private Environment environment;

   @Before
   public void setup(){
    logger.info("Profiles: {}", Arrays.toString(environment.getActiveProfiles()));
   }

   //@Test disable
   public void someTest(){

     assertThat(...)

   }

    @ActiveProfiles(resolver=TestJdbcActiveProfilesResolver.class)
    public static class ForJdbc extends PersonaServiceImplTest {

        public ForJdbc(Persona persona){
            super(persona);
        }

        @Test
        @Override
        @Sql(scripts={"classpath:/.../script.sql"})//when be necessary
        public void someTest()(){
            super.someTest()();
        }

      }

    @ActiveProfiles(resolver=TestHibernateActiveProfilesResolver.class)
    public static class ForHibernate extends PersonaServiceImplTest {

        public ForHibernate(Persona persona){
            super(persona);
        }

        @Test
        @Override
        @Sql(scripts={"classpath:/.../script.sql"})//when be necessary
        public void someTest()(){
            super.someTest()();
        }

        ...

      }

   }

注意事项:

  • 外部类(outer class)必须是抽象的(abstract)
  • 外部类(outer class)不能声明@ActiveProfiles
  • 外部类(outer class)包含需要测试的方法,每个方法不得声明@Test
  • Environment是可选的,但用于让每个静态嵌套类(static nested class)知道其激活的配置文件。可以通过带有@Before注释的公共方法实现
  • 每个静态嵌套类(static nested class)必须是public
  • 每个静态嵌套类(static nested class)必须扩展外部类(outer class)
  • 每个静态嵌套类(static nested class)必须声明@ActiveProfiles
  • 每个静态嵌套类(static nested class)覆盖每个测试方法,只需使用super调用相应的重写方法
  • 每个静态嵌套类(static nested class)对于每个测试覆盖的方法,必须有@Test
  • @Sql不能重用,必须为每个覆盖的方法声明

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接