Java 在JUnit4中重用测试实现?
我有一个接口,例如:Java 在JUnit4中重用测试实现?,java,unit-testing,junit4,code-reuse,Java,Unit Testing,Junit4,Code Reuse,我有一个接口,例如: public interface Thing { FrobResult frob(FrobInput); } 以及我尝试测试的该接口的几种实现(例如,NormalThing,ImmutableThing,asynchthing) 我的许多测试方法实际上都是为了确保正确实现接口,从而在每个实现中复制接口。在JUnit3中,一个常见的解决方案是创建一个基类(扩展TestCase),然后由每个实现类对该基类进行子类化。但是这是JUnit4的正确方法吗 (我相信)按偏好的升
public interface Thing {
FrobResult frob(FrobInput);
}
以及我尝试测试的该接口的几种实现(例如,NormalThing
,ImmutableThing
,asynchthing
)
我的许多测试方法实际上都是为了确保正确实现接口,从而在每个实现中复制接口。在JUnit3中,一个常见的解决方案是创建一个基类(扩展TestCase
),然后由每个实现类对该基类进行子类化。但是这是JUnit4的正确方法吗
(我相信)按偏好的升序排列的可能选择:
剪切粘贴重复的测试方法。一点也不枯燥,但我想在测试中不如在生产代码中那么令人担忧
使用@Test
方法创建一个抽象类,并为每个实现测试类对其进行子类化。(常见于JUnit3测试——在JUnit4中这仍然是一个好方法吗?)
将公共测试方法放入助手类中,并在每个实现中调用它。(合成而不是继承。)
最好的做法是什么?可能是一个@RunWith(Parameterized.class)
测试,它是通过每个实现参数化的?或者有更好的方法来实现这一点吗?是的,这是创建基类的正确方法,然后由JUnit4中的每个实现类对基类进行子类化
我更喜欢接口的基本测试类是抽象的,即您的“备选方案”2,因为我在模拟测试代码的生产代码的继承层次结构方面有很好的经验。因此,如果您有接口I
和实现S1
、S2
和S3
,您就可以创建抽象测试类TestI
和测试类TestS1
、TestS2
和TestS3
测试用例应该是说话的,即讲述一个故事。像往常一样,通过仔细选择方法名称并仅使用干净的行为子类型,继承不会混淆这一点。我对JUnit和测试用例使用#2方法。这是最方便和易于维护的。它也很容易被接受(因为它在OOD中固有的基类具有通用方法)。
对我来说,单元测试类和常规项目类并没有什么不同……所以我确实应用了类似的设计考虑 是的,在JUnit4中创建一个基类,然后再由每个实现类进行子类化也是正确的方法。@DaveBall:你介意把它作为一个答案吗?#3会更好,我同意你下面的评论,认为这应该是可能的。这也是我的第一个想法,虽然感觉应该有一些新的和闪亮的方法来混合测试方法,因为这似乎是一种常见的情况+1但是在给你打勾之前,我会等待其他人的加入。的确,测试类需要考虑设计因素,但我不会说它们与常规项目类没有什么不同。但无论哪种方式,我都倾向于遵循有效的Java第16条:支持组合而不是继承。继承(实际上是创建一个“是-是”关系)通常是实现代码重用的一个糟糕的方法。。。通常我会同时使用合成和继承。一些只属于我放在基类中的层次结构的基本功能,以及一些可以在我的层次结构之外重用的功能(即库/组件元素),我放在组合中。因此,您应该同时使用#2和#3方法(我在这里补充了我的答案):)