如何正确关闭 JUnit-Runner?

How to correctly shut down a JUnit-Runner?

我通过实现 org.junit.runner.Runner 创建了自己的 JUnit-Runner,这样我就可以 运行 使用 @RunWith-Annotation 与他们一起进行单元测试。

看起来有点像这样:

public class MyRunner extends Runner {

    private Context myContext;
    myContext.init();
    private final BlockJUnit4ClassRunner runner;

    public MyRunner(final Class<?> clazz) throws InitializationError {
        myContext = new Context();

        runner = new BlockJUnit4ClassRunner(clazz);
    }

    @Override
    public void run(final RunNotifier notifier) {
        runner.run(notifier);
    }

    @Override
    public Description getDescription() {
        return runner.getDescription();
    }

    public void filter(final Filter filter) throws NoTestsRemainException {
        runner.filter(filter);
    }
}

要清理资源,我必须通过调用 MyContext.close() 来关闭 MyContext。我应该在哪里调用它,以便在测试 运行?

之后清理我的资源

Where should I invoke this so that my resources are cleand up after the tests have run ?

更新了我的答案,您可以使用 org.junit.runner.notification.RunListener,如下所示:

(1) 创建自己的 RunListener class:

public class MyRunnerListener extends RunListener {
    private Context context;

    public MyRunnerListener(Context context) {
        this.context = context;
    }

     void   testRunFinished(Result result)  {
          context.close();
     }
}

(2) 在 MyRunner 中使用 MyRunnerListener :

public class MyRunner extends Runner {

    private Context myContext;
    MyRunnerListener runnerListener;
    private final BlockJUnit4ClassRunner runner;

    public MyRunner(final Class<?> clazz) throws InitializationError {
        myContext = new Context();
        myContext.init();
        runnerListener = new MyRunnerListener(myContext);

        runner = new BlockJUnit4ClassRunner(clazz);
    }

    @Override
    public void run(final RunNotifier notifier) {
        notifier.addListener(runnerListener);
        runner.run(notifier);
    }

    @Override
    public Description getDescription() {
        return runner.getDescription();
    }

    public void filter(final Filter filter) throws NoTestsRemainException {
        runner.filter(filter);
    }
}

P.S.: 如果您不想使用 Runner,那么您可以按照 Markus 的回答(使用 TestRule,而不是TestRunner).

我不确定你想要达到什么目的,但你是否已经看过 JUnit's Rules?

public class MyContextRule extends ExternalResource {

    private final Context myContext;

    public MyContextRule()  {
        myContext = new Context();
    }

    @Override
    protected void before() throws Throwable {
        myContext.init();
    }

    @Override
    protected void after() {
        myContext.close();
    }

}

用法:

public class MyTest {
    @ClassRule
    public static MyContextRule contextRule = new MyContextRule(); 

    //...
}

JUnit Rule 优于 Runner 的优势在于您可以拥有多个,而您只能拥有一个跑步者。

因此,您的自定义 Rule 可以与您将来可能遇到的随机测试框架引入的任何运行程序一起使用...