I have a presentation class storing an XYChart.Series object and updating it by observing the model. The Series updating is done by using Platform.runLater(...)
I want to unit-test this, making sure the commands in runLater are performed correctly. How do I tell the unit-test to wait for the runLater commands to be done?
Right now all I do is Thread.Sleep(...) on the test-thread to give the FXApplicationThread the time to complete, but that sounds stupid.
The way I solved it is as follows.
1) Create a simple semaphore function like this:
public static void waitForRunLater() throws InterruptedException {
Semaphore semaphore = new Semaphore(0);
Platform.runLater(() -> semaphore.release());
semaphore.acquire();
}
2) Call waitForRunLater()
whenever you need to wait. Because Platform.runLater()
(according to the javadoc) execute runnables in the order they were submitted, you can just write within a test:
...
commandThatSpawnRunnablesInJavaFxThread(...)
waitForRunLater(...)
asserts(...)`
which works for simple tests
To have it more in AssertJ style syntax, you can do something like this:
@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();
}
}
You could use a CountDownLatch which you create before the runLater and count down at the end of the Runnable