0

我正在通过一个ScheduledExecutorService作为合作者的单位进行 TDD。这个单元有一个start方法,它基本上用任务启动执行程序,我现在想编写驱动该stop方法的测试,因为我知道没有人会调用ScheduledExecutorService.shutdown线程将挂起(默认情况下不是守护线程)。

我想通过@Test(timeout = 5000L)并使用实际的执行程序服务(而不是确定性服务)来构建单元,但我面临的问题是由于某种原因测试没有挂起。
我认为,不确定,这与 Intellij/Junit 混合调用system.exit和杀死“我的”jvm 有关。

在我用一种main方法编写的手动“测试”中,我可以验证在不调用该shutdown方法的情况下系统确实卡住了。

关于如何测试这个的任何想法?

谢谢

更新
我整理了一个小代码示例来说明问题:

public class SomethingTest {
@Test(timeout = 5000L)
public void shouldStopExecutorServiceWhenStopped2() throws InterruptedException {
    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    Something cds = new Something(scheduler);
    cds.start();
    Thread.sleep(2000); //this is to be pretty sure that the scheduling started since I'm not certain the thread will deterministically block otherwise
}

public static void main(String[] args) throws InterruptedException {
    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    Something cds = new Something(scheduler);
    cds.start();
    Thread.sleep(2000); //this is to be pretty sure that the scheduling started since I'm not certain the thread will deterministically block otherwise
    cds.stop(); //comment this out to see that it hangs if shutdown isn't called
}
public static class Something {
    private final ScheduledExecutorService scheduler;

    public Something(ScheduledExecutorService scheduler) {
        this.scheduler = scheduler;
    }

    public void start() {
        scheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("did something really important over time");
            }
        }, 0, 5, TimeUnit.SECONDS);
    }

    public void stop() {
        scheduler.shutdownNow();
    }
} }
4

2 回答 2

1

除了超时,您应该有一个明确的规则,您将在您的案例中进行测试。

例如,让测试运行一段时间(在您的情况下为 2 秒),然后断言它确实完成了它的工作,例如在调度程序上的 isTerminated() 或 isShutDown() 上的一些断言。

但是,您运行测试的方式总是会在 5 秒之前结束,因为测试线程不会等待调度程序完成。

另一种选择是像这样放置一个while循环(也可以是 isShutDown() 取决于您的需要):

while (!scheduler.isTerminated()) sleep(2000);

如果需要超过 5 秒,这应该会使您的测试失败,并且您将让测试线程等待调度程序真正完成或调度程序的执行时间超过您设置的超时时间。

于 2013-07-14T12:25:04.980 回答
0

我想我要做的(现在没有时间)是编写一个与 Timeout 规则非常相似的 JUnit TestRule,它在完成之前检查是否有任何非守护线程在运行。
本质上,如果有任何非守护线程正在运行,我希望测试失败,因为我想验证系统在这个伪块之后不会挂起,new unit();unit.start;unit.stop而且我知道如果没有守护线程将在之后运行,系统不会挂起一段时间(输入超时以使测试具有确定性并为 jvm 提供实际关闭该线程的选项)。

于 2013-07-15T07:46:57.553 回答