如何对JavaFX应用程序启动进行单元测试
我有一个JavaFX应用程序,我想测试它是否启动。我该怎么做呢?是否可以只使用JUnit,或者TestFX可以在这方面帮助我 我的主要问题是:如何在应用程序(成功)启动后立即关闭它 示例应用程序类:如何对JavaFX应用程序启动进行单元测试,java,unit-testing,javafx,javafx-8,testfx,Java,Unit Testing,Javafx,Javafx 8,Testfx,我有一个JavaFX应用程序,我想测试它是否启动。我该怎么做呢?是否可以只使用JUnit,或者TestFX可以在这方面帮助我 我的主要问题是:如何在应用程序(成功)启动后立即关闭它 示例应用程序类: public class MovieDB extends Application { @Override public void start(final Stage primaryStage) throws IOException { FXMLLoader fxmlL
public class MovieDB extends Application {
@Override
public void start(final Stage primaryStage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(MovieDBController.class.getResource("MovieDB.fxml"), ResourceBundle.getBundle("bundles/bundle", new Locale("en")));
Parent root = fxmlLoader.load();
Scene scene = new Scene(root, 1024, 768);
StyleManager.getInstance().addUserAgentStylesheet(getClass().getResource("/css/MovieDB.css").getPath());
primaryStage.setTitle("MovieDB");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
假设primaryStage是唯一打开的阶段,那么当您调用primaryStage.hide()时,JavaFX线程将自动关闭。这是因为当所有阶段都隐藏时,JavaFX默认设置为shutdown,可以通过调用
Platform.setImplicitExit(false)
进行更改
更多信息。由于该方法在应用程序退出之前不会返回,无论是通过调用还是关闭所有应用程序窗口,因此您必须将其包装到另一个线程中才能终止它
如果在JavaFX应用程序启动后立即调用Platform.exit,您将获得IllegalStateException。如果您等待一段时间以便初始化JavaFX应用程序,然后调用Platform.exit,则JavaFX应用程序和包装线程都将终止,而不会完成或引发任何异常。我无法通过使用Platform.exit找到解决这个问题的方法
然而,我通过使用Thread.interrupt成功地做到了这一点。只需在包装线程内运行JavaFX应用程序,等待一段时间,然后中断包装线程。这样JavaFX应用程序将被中断并抛出InterruptedException。如果它没有抛出,那么启动JavaFX应用程序就会出现问题
请注意,启动JavaFX应用程序可能需要比等待JVM更长的时间,因此此方法不能保证JavaFX应用程序在正确启动后被中断,这可能会导致误报情况。
测试班
JavaFX应用程序类
应用程序。启动
签名不是对象
或?
。它是Application.launch(
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class JavaFXTest {
// Wrapper thread updates this if
// the JavaFX application runs without a problem.
// Declared volatile to ensure that writes are visible to every thread.
private volatile boolean success = false;
/**
* Test that a JavaFX application launches.
*/
@Test
public void testMain() {
Thread thread = new Thread() { // Wrapper thread.
@Override
public void run() {
try {
Application.launch(JavaFXTest.class); // Run JavaFX application.
success = true;
} catch(Throwable t) {
if(t.getCause() != null && t.getCause().getClass().equals(InterruptedException.class)) {
// We expect to get this exception since we interrupted
// the JavaFX application.
success = true;
return;
}
// This is not the exception we are looking for so log it.
Logger.getLogger(JavaFXTest.class.getName()).log(Level.SEVERE, null, t);
}
}
};
thread.setDaemon(true);
thread.start();
try {
Thread.sleep(3000); // Wait for 3 seconds before interrupting JavaFX application
} catch(InterruptedException ex) {
// We don't care if we wake up early.
}
thread.interrupt();
try {
thread.join(1); // Wait 1 second for our wrapper thread to finish.
} catch(InterruptedException ex) {
// We don't care if we wake up early.
}
assertTrue(success);
}
}
import java.io.IOException;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class JavaFX extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException {
primaryStage.setTitle("JavaFX");
Label label = new Label("Hello World!");
StackPane root = new StackPane();
root.getChildren().add(label);
primaryStage.setScene(new Scene(root, 250, 250));
primaryStage.show();
}
}