我正在尝试为一些广泛使用的接口编写合同测试:
遵循:
public abstract class MyInterfaceContractTest extends TestCase {
private MyInterface _toTest;
public void setUp(){
_toTest = getTestableImplementation();
}
protected abstract MyInterface getTestableImplementation();
public void testContract(){
}
}
...和...
public class MyInterfaceImplementationTest extends MyInterfaceContractTest {
protected MyInterface getTestableImplementation(){
return new MyInterfaceImplementation(...);
}
}
但是,我希望能够测试MyInterfaceImplementation
的多个实例。在我的用例中,这是一个包含数据集合的不可变对象(根据接口MyInterface
指定访问器),它可能是空的,或者有少量数据,甚至是大量数据。
所以问题是,如何测试我的实现的多个实例?
目前,我必须初始化实现以将其传递给抽象合同测试。一种方法是为每个实现提供多个测试类,其中每个测试类测试该实现的特定实例 - 但这似乎有点庞大且难以跟踪。
FWIW,我正在使用JUnit 3。
答案 0 :(得分:3)
通常,方法是使用抽象类的“可测试”子类在一次测试中测试抽象类的所有功能。然后为每个具体实现编写一个单独的测试,测试在具体类中定义/实现的方法(不要重新测试具体类中的功能)。
答案 1 :(得分:2)
如果我已正确理解您的需求,您希望运行相同测试方法或多个相同接口的实现方法。
我不知道如何在JUnit 3中做得很好。
如果您愿意升级到JUnit 4,可以使用参数化测试来完成。
对于在接口的两个实现上运行单个测试方法的简单示例,您的测试代码可能如下所示:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static junit.framework.Assert.assertEquals;
// Tell JUnit4 to run it as a parametrized test.
@RunWith(Parameterized.class)
public class MyInterfaceContractTest {
private MyInterface _toTest;
// Load the test data into your test instance via constructor
public MyInterfaceContractTest(MyInterface impl) {
this._toTest = impl;
}
// Supply the test data, in this example just the two implementations you want to test.
@Parameterized.Parameters
public static Collection<Object[]> generateData() {
return Arrays.asList(new Object[]{new MyInterfaceImpl1()}, new Object[]{new MyInterfaceImpl2()});
}
@Test
public void testContract(){
// assert whatever, using your _toTest field
}
}
在运行此测试时,JUnit将运行测试两次,使用参数列表中的连续条目调用构造函数。
如果你有更复杂的事情,比如对不同实现的不同期望,数据生成可以返回包含多个元素的Object数组列表,然后构造函数将获取相应的多个参数。
如果您需要在测试方法之间重新初始化测试对象,您可能还想使用我在this related question中描述的技巧。
我相信TestNG中可能存在类似的事情,这可能是升级路径的另一种选择。