我一直在设置一些合同JUnit 4测试(按照question的回答提供建议) - 例如如果我有一个接口(我在示例中包含了泛型,因为我在我的项目中使用它们) - 但是,这是一个非常简单的示例:
public interface MyInterface<T> {
public T myMethod();
}
我可以创建一个抽象的合同测试 - 例如:
public abstract class AbstractMyInterfaceTest<T> {
private final MyInterface<T> _impl;
// plus, store stuff to test against;
public AbstractMyInterfaceTest(MyInterface<T> impl, ... stuff to test against){
_impl = impl;
// stuff to test against...
}
@Test
public void testMyMethod(){
// test some stuff...
}
}
...并为每个实现扩展这个抽象测试类(我使用@RunWith(Parameterized.class)
运行)。我也传递了一些变量来测试接口的实现,反对抽象测试类。
然而,实际上,一些接口返回的是其他接口实现的对象,我希望能够使用该接口的抽象合同类(以及相关变量)来测试此实现。例如,MyInterface
中的方法可能会返回迭代器 - 这是一个接口。我有一个单独的AbstractIteratorTest
,它针对一组值运行Iterator的合同测试,我想检查Iterator
的实现返回的MyInterface
是否通过了合同测试AbstractIteratorTest
具有预期的值集。
目前,我正在将以下内容添加到抽象测试类中:
// N.b. not setting @Test - so doesn't run all tests twice...
public void runTests(){
testMyMethod();
// etc.
}
但是,这并不是独立运行每个测试(例如,在每个测试方法之前运行setUp()
),因此如果这些合同测试期望每个测试的实现都处于特定状态,则会出现问题。 (一个具体的例子是测试Iterator
接口的实现,其中每个测试方法都可以改变测试Iterator
的状态
有没有更好的方法来实现这一点,也许是利用JUnit 4中的功能?
我见过有关@RunWith(Suite.class)
注释的内容,但这似乎是关于从单个测试类运行多个测试类,并且不允许您将变量传递到正在进行的不同测试类中跑。可能有一种方法可以使用这个Suite
来解决我的问题,但我不确定它是什么......
答案 0 :(得分:0)
首先,如果您是抽象测试类的子类,则不需要使用Parameterized
。您可以使用Parameterized
而不是子类,但您不太可能需要两者。除非你想测试每个实现的多个实例,我将在下面演示!
执行此操作的一种方法是使返回实例的测试只是AbstractAnotherInterfaceTest
的更多子类或参数。
说你有:
public abstract class AbstractAnotherInterfaceTest {
private AnotherInterface instance;
protected AbstractAnotherInterfaceTest(AnotherInterface instance) {
this.instance = instance;
}
@Test
public void everythingIsOkay() {...}
}
你有:
public class Pony implements AnotherInterface { ... }
public class PonyProducingMyInterface implements MyInterface<Pony> { ... }
你可以写:
@RunWith(Parameterized.class)
public class PonyTest extends AbstractAnotherInterfaceTest {
@Parameterized.Parameters
public static Collection<Pony> ponies() {
return Arrays.asList(
new Pony(), // base case
new PonyProducingMyInterface().myMethod() // testing the factory
);
}
public PonyTest(Pony instance) {
super(pony);
}
}
这无疑是有点奇怪,因为new PonyProducingMyInterface().myMethod()
案例确实是对PonyProducingMyInterface
的测试,但归类为AbstractAnotherInterfaceTest
。
我能想到的唯一方法就是在AbstractAnotherInterfaceTest
的某个子类中使用AbstractMyInterfaceTest
测试来编写一个知道如何设置实例的自定义ParentRunner
AbstractAnotherInterfaceTest
作为AbstractMyInterfaceTest
个体的子项{{1}}。您可能希望使用注释来指导流程,使其有点通用。