在 JUnit 4 中重用测试实现?

2022-09-04 22:46:26

我有一个接口,例如:

public interface Thing {
  FrobResult frob(FrobInput); 
}

以及我正在尝试测试的该接口的几个实现(例如,,)。NormalThingImmutableThingAsyncThing

我的许多测试方法实际上是为了确保接口正确实现,因此在每个实现中都是重复的。在 JUnit 3 中,一个常见的解决方案是创建一个基类(扩展),然后由每个实现类子类化。但这是JUnit 4的正确方法吗?ThingTestCase

(我相信)偏好升序的可能替代方案:

  1. 剪切粘贴重复的测试方法。一点也不 DRY,但我想在测试中比在生产代码中更令人担忧。

  2. 创建一个包含方法的抽象类,并为每个实现测试类对其进行子类化(在 JUnit 3 测试中很常见 - 这仍然是 JUnit 4 中的好方法吗?@Test

  3. 将常用测试方法放入帮助器类中,并在每个实现上调用它。(组成而不是继承。

执行 #3 的最佳做法是什么?也许是每个实现参数化的测试?还是有更好的方法来实现这一目标?@RunWith(Parameterized.class)


答案 1

是的,创建一个基类是正确的方法,然后由 JUnit4 中的每个实现类子类进行子类化。

我更喜欢接口的基本测试类是抽象的,即你的“替代”2,因为我在模拟测试代码的生产代码的继承层次结构方面已经积累了丰富的经验。因此,如果你有接口 I 和实现 ,和 ,你就会得到抽象测试类 TestI 和测试类 和 。S1S2S3TestS1TestS2TestS3

测试用例应该是说话,即讲述一个故事。通过像往常一样仔细选择方法名称并仅使用干净的行为子类型,继承不会对此进行混淆。


答案 2

我对JUnit和TestNG测试用例使用#2方法。这是最方便和易于维护的。它也直接拿起(因为它的原生OOD具有具有通用方法的基类)。对我来说,单元测试类与常规项目类没有什么不同...所以我确实应用了类似的设计考虑因素。


推荐