Junit 4 - 在测试类中运行所有测试

时间:2012-07-05 18:26:11

标签: java unit-testing interface junit4

我一直在设置一些合同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来解决我的问题,但我不确定它是什么......

1 个答案:

答案 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}}。您可能希望使用注释来指导流程,使其有点通用。