JavaFX 应用程序线程在 JUnit 测试期间退出

JavaFX application thread exits during JUnit test

我正在使用 JUnit 测试 JavaFX 应用程序,在大多数情况下,我使用 Basic JUnit test for JavaFX 8 中的 @Rule 方法。然而,在某些情况下这种方法不起作用,所以我手动设置 JavaFX 平台,并在必要时调用 Platform.runLater()。

似乎正在发生的事情是,在某些时候 JavaFX 应用程序线程正在消失,这意味着后续测试锁定,因为 Platform.runLater() 调用永远不会 return - 这就是我添加的原因例如超时。我已经通过调用 Thread.getAllStackTraces()

证明了这一点

代码

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;
    }

}

输出...JavaFX 应用程序线程在那里,然后就消失了...

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]

关卡关闭似乎触发了 "implicit exit"。我仍然有兴趣知道为什么这不会影响使用 @Rule 方法的测试...

解决方法:

Platform.setImplicitExit(false)