强制执行JUnit子类测试会覆盖@BeforeClass方法

时间:2013-11-06 20:19:30

标签: java junit parameterized-tests

我有一个轻量级的测试框架,编写为JUnit Abstract测试。我想要做的是让实现子类定义他们的自定义测试类设置。我的计划是让抽象超类定义一个@BeforeClass方法,该方法调用一个抽象的安装方法,每个子类都将被强制定义,但这会失败,因为@BeforeClass方法必须是静态的,静态方法不能做成抽象也不能调用实例方法。

我可以假设子类将通过包含文档中所需的内容或抛出IllegalStateException来进行设置,但我真的希望能够在接口级别强制执行此操作。原因。任何人都可以想到解决这个问题吗?

顺便说一句,我对使这些测试参数化有同样的问题(子类定义参数,但@Parameters带注释的方法必须是静态的)。我通过运行第三方JUnitParams运行器来解决这个问题,该运行器允许使用方法级参数。请在此处查看:https://github.com/Pragmatists/JUnitParams

4 个答案:

答案 0 :(得分:1)

对于您的主要问题,为什么不使您的父类抽象并使用@Before注释而不是@BeforeClass?例如:

public abstract class TestParent {
   @Before
   public void setup() {
     doSetup();
   }

   protected abstract void doSetup();

   // other stuff...
}

public class RealTest extends TestParent {
    protected void doSetup() {
      // custom setup
    }

    // custom tests...
}

这将强制子类重新定义doSetup()方法,而不使用静态方法。

答案 1 :(得分:1)

一个选项是让子类实现一个静态doSetupOnce()方法,并从基类@BeforeClass方法中反向查找和调用该方法。由于这需要是一个静态方法,因此只能在运行时强制执行它。

另一种方法是在基类中使用抽象doSetupOnce实例方法,该方法在第一次调用父项@Before方法时调用。这会在编译时强制执行该问题,但是实现者必须小心不要从此方法访问实例字段(因为这可能不是他们想要的)。

一般情况下(并且不知道您的具体情况),我不太喜欢这些方法中的任何一种,而是宁愿让实现者在需要时声明@BeforeClass方法。将它们锁定在严格的基类方案中会导致比解决的问题更多的问题。还要考虑使用JUnit规则,这通常是比基类更好的选择(例如,因为它们是可组合的)。当然,您也可以将这两种方法结合起来,主要依赖于JUnit规则,另外还提供了一些带有预定义规则的基类,以方便使用。

答案 2 :(得分:1)

这可能超出范围或矫枉过正,但我​​认为值得一提,因为它们并没有那么不同。因此,我正在迈出一大步,建议您可以尝试TestNG,因为使用@BeforeClass注释的方法不一定是静态的,也不能用@Parameters注释。

您可以阅读2个框架here之间的差异,看起来他们也支持migrating JUnit tests to TestNG

答案 3 :(得分:1)

我认为不可能以干净的OO方式做到这一点。 @BeforeClass不仅是一个静态方法,而且JUnit会在孩子的@BeforeClass之前调用父级@BeforeClass

无论如何,你试图这样做必须暴露父类的内部静态,所以子类可以设置父类的字段,打破封装。

我认为最好的方法是使用@Before,但也有一个静态标志,如果之前已经调用了该方法,那么至少你可以短路并且只对第一次调用进行初始化。