0

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

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

顺便说一句,我在将这些测试参数化时遇到了同样的问题(子类定义了参数,但带@Parameters注释的方法必须是静态的)。我通过使用允许方法级参数的第 3 方 JUnitParams 运行程序来解决这个问题。在这里查看:https ://github.com/Pragmatists/JUnitParams

4

4 回答 4

1

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

你可以在这里阅读这两个框架之间的差异,看起来它们也支持将JUnit 测试迁移到 TestNG

于 2013-11-06T21:04:01.777 回答
1

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

无论如何,您尝试这样做必须暴露父类的内部静态状态,以便子类可以设置父类的字段,从而破坏封装。

我认为最好的方法是使用@Before,但也有一个静态标志来设置该方法是否已经被调用过,这样至少你可以短路并且只为第一次调用做初始化......

于 2013-11-06T21:05:02.600 回答
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() 方法。

于 2013-11-06T20:27:07.787 回答
1

一种选择是让子类实现一个静态doSetupOnce()方法,然后从基类方法反射性地查找和调用该@BeforeClass方法。由于这需要是一个静态方法,它的存在只能在运行时强制执行。

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

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

于 2013-11-06T20:46:30.403 回答