Java 在单元测试中等待Platform.RunLater

Java 在单元测试中等待Platform.RunLater,java,unit-testing,javafx-2,javafx-8,Java,Unit Testing,Javafx 2,Javafx 8,我有一个表示类,它存储一个XYChart.Series对象,并通过观察模型来更新它。系列更新是使用Platform.runLater(…)完成的 我想对此进行单元测试,确保runLater中的命令正确执行。我如何告诉单元测试等待runLater命令完成? 现在我所做的就是在测试线程上执行Thread.Sleep(…),给FXApplicationRead一个完成的时间,但这听起来很愚蠢。您可以使用在runLater之前创建的倒计时锁存器,并在Runnable结束时倒计时。我解决它的方法如下 1)

我有一个表示类,它存储一个XYChart.Series对象,并通过观察模型来更新它。系列更新是使用Platform.runLater(…)完成的

我想对此进行单元测试,确保runLater中的命令正确执行。我如何告诉单元测试等待runLater命令完成?
现在我所做的就是在测试线程上执行Thread.Sleep(…),给FXApplicationRead一个完成的时间,但这听起来很愚蠢。

您可以使用在runLater之前创建的倒计时锁存器,并在Runnable结束时倒计时。

我解决它的方法如下

1) 创建一个简单的信号量函数,如下所示:

public static void waitForRunLater() throws InterruptedException {
    Semaphore semaphore = new Semaphore(0);
    Platform.runLater(() -> semaphore.release());
    semaphore.acquire();

}
    @Test
    public void test() throws InterruptedException {
        // do test here

        assertAfterJavaFxPlatformEventsAreDone(() -> {
            // do assertions here
       }
    }

    private void assertAfterJavaFxPlatformEventsAreDone(Runnable runnable) throws InterruptedException {
        waitOnJavaFxPlatformEventsDone();
        runnable.run();
    }

    private void waitOnJavaFxPlatformEventsDone() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        Platform.runLater(countDownLatch::countDown);
        countDownLatch.await();
    }
}
2) 在需要等待时调用waitForRunLater()。因为
Platform.runLater()
(根据javadoc)按照提交的顺序执行runnables,所以您可以在测试中编写:

...
commandThatSpawnRunnablesInJavaFxThread(...)
waitForRunLater(...)
asserts(...)`

它适用于简单测试

要使其更符合AssertJ风格的语法,可以执行以下操作:

public static void waitForRunLater() throws InterruptedException {
    Semaphore semaphore = new Semaphore(0);
    Platform.runLater(() -> semaphore.release());
    semaphore.acquire();

}
    @Test
    public void test() throws InterruptedException {
        // do test here

        assertAfterJavaFxPlatformEventsAreDone(() -> {
            // do assertions here
       }
    }

    private void assertAfterJavaFxPlatformEventsAreDone(Runnable runnable) throws InterruptedException {
        waitOnJavaFxPlatformEventsDone();
        runnable.run();
    }

    private void waitOnJavaFxPlatformEventsDone() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        Platform.runLater(countDownLatch::countDown);
        countDownLatch.await();
    }
}

如果JavaFX线程引发异常,则可能需要将semaphore.release()包装在try finally块中