Reputation: 36743
I'm testing a JavaFX application with JUnit, In most cases I use the @Rule approach from Basic JUnit test for JavaFX 8. However there are a couple of situations where this approach does not work, so I setup the JavaFX platform manually, and call Platform.runLater() where necessary.
What appears to be happening is that at some point the JavaFX application thread is disappearing, this means subsequent tests lockup as the Platform.runLater() calls never return - that's why I've added timeouts in example. I've proved this with calls to Thread.getAllStackTraces()
Code
public class JavaFxThreadJUnit {
private static boolean setup;
private Stage stage;
@Before
public void before() throws Exception {
setupJavaFX();
Platform.setImplicitExit(true);
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
stage = new Stage();
stage.show();
latch.countDown();
});
latch.await(5, TimeUnit.SECONDS);
}
@After
public void after() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
stage.hide();
latch.countDown();
});
latch.await(5, TimeUnit.SECONDS);
}
@Test
public void foo() throws Exception {
// test stuff...
System.out.println("foo test: "
+ Thread.getAllStackTraces().keySet().stream().map(Thread::getName).collect(Collectors.toList()));
}
@Test
public void bar() throws Exception {
// test stuff...
System.out.println("bar test: "
+ Thread.getAllStackTraces().keySet().stream().map(Thread::getName).collect(Collectors.toList()));
}
// https://gist.github.com/andytill/3835914
public static void setupJavaFX() throws InterruptedException {
if (setup) {
return;
}
long timeMillis = System.currentTimeMillis();
final CountDownLatch latch = new CountDownLatch(1);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// initializes JavaFX environment
new JFXPanel();
latch.countDown();
}
});
System.out.println("javafx initialising...");
latch.await();
System.out.println("javafx is initialised in " + (System.currentTimeMillis() - timeMillis) + "ms");
setup = true;
}
}
Output... JavaFX Application Thread was there, then it's gone...
javafx initialising...
javafx is initialised in 327ms
bar test: [Thread-3, ReaderThread, AWT-Shutdown, AWT-Windows, Thread-2, Finalizer, JavaFX Application Thread, Signal Dispatcher, Java2D Disposer, AWT-EventQueue-0, main, Attach Listener, Reference Handler, QuantumRenderer-0]
foo test: [Thread-3, ReaderThread, Java2D Disposer, AWT-Windows, Thread-2, main, Finalizer, Attach Listener, Reference Handler, Signal Dispatcher]
Upvotes: 1
Views: 1111
Reputation: 36743
Looks like the stage closing is triggering an "implicit exit". I'd still be interested to know why this doesn't also affect tests using the @Rule approach...
Workaround:
Platform.setImplicitExit(false)
Upvotes: 1