Wait for Platform.RunLater in a unit test
Asked Answered
R

3

9

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.

Rebroadcast answered 2/4, 2014 at 19:26 Comment(0)
R
9

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

Rebroadcast answered 3/4, 2014 at 19:11 Comment(1)
May need to wrap semaphore.release() in a try-finally block if JavaFX thread throws an exceptionCrossed
O
1

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();
    }
}
Oaken answered 11/9, 2019 at 8:27 Comment(0)
S
0

You could use a CountDownLatch which you create before the runLater and count down at the end of the Runnable

Seldan answered 2/4, 2014 at 21:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.