如何测试JavaFX控制器的方法?
How to test method of JavaFX controller?
我正在尝试使用 TestFX 来测试我的应用程序。我想 运行 测试我的控制器的方法。
Main.java:
public class Main extends Application {
try{
new Flow(ManageCtrl.class).startInStage(primaryStage);
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
ManageCtrl.java:
@ViewController("/FPManage.fxml")
public class ManageCtrl extends AnchorPane {
@FXML // fx:id="email"
private TextField email; // Value injected by FXMLLoader
public void setEmail(String address) {
this.email.setText(address);
}
}
ManageCtrlTest.java:
public class ManageCtrlTest extends ApplicationTest {
@Override
public void start(Stage stage) {
try {
new Flow(ManageCtrl.class).startInStage(stage);
} catch (FlowException ex) {
Logger.getLogger(ManageCtrlTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Test
public void testSetEmail() {
ManageCtrl instance = new ManageCtrl();
instance.setEmail("test@gmai.com");
assertEquals("test@gmail.com", ((TextField)GuiTest.find("#email")).getText());
}
}
但我得到以下异常:
testSetEmail Failed: java.lang.illegalStateException: Not on FX application thread; currentThread = Test worker
java.lang.illegalStateException: Not on FX application thread; currentThread = Test Worker
感谢您的帮助。
IllegalStateException
与 JavaFX 和 TestFX 的性质有关。
ManageCtrl
从 AnchorPane
扩展,它是 JavaFX 的 Scene
对象之一,所有这些对象都需要在 JavaFX 线程(也称为 JavaFX 应用程序线程或 JavaFX 用户线程)中构建.您可以使用 ApplicationTest#interact
在 JavaFX 线程中构造 ManageCtrl
:
interact(() -> {
ManageCtrl controller = new ManageCtrl();
controller.setEmail("test@gmail.com");
});
然而,这将引发 NullPointerException
,这是由与 new Flow(ManageCtrl.class)
一起使用的 DataFX 的 特性引起的。
new Flow(ManageCtrl.class).startInStage(stage)
将使用您的 @ViewController
中定义的对象注入控制器中所有 @FXML
注释的字段 - new ManageCtrl()
不会。我们可以通过在测试前在字段controller
中构造ManageCtrl
来解决这个问题:
@Override
public void start(Stage stage) throws Exception {
Flow flow = new Flow(ManageCtrl.class);
// create a handler to initialize a view and a sceneRoot.
FlowHandler handler = flow.createHandler();
StackPane sceneRoot = handler.start();
// retrieve the injected controller from the view.
FlowView view = handler.getCurrentView();
controller = (ManageCtrl) view.getViewContext().getController();
// attach the sceneRoot to stage.
stage.setScene(new Scene(sceneRoot));
stage.show();
}
您现在可以使用以下方法测试您的控制器:
@Test
public void should_set_email() throws Exception {
// when:
interact(() -> {
controller.setEmail("test@gmail.com");
});
// then:
verifyThat("#email", hasText("test@gmail.com"));
}
在试图简化这方面测试的 issue on GitHub. I've also created a pull request on Bitbucket 中详细介绍了整个事情。
我正在尝试使用 TestFX 来测试我的应用程序。我想 运行 测试我的控制器的方法。
Main.java:
public class Main extends Application {
try{
new Flow(ManageCtrl.class).startInStage(primaryStage);
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
ManageCtrl.java:
@ViewController("/FPManage.fxml")
public class ManageCtrl extends AnchorPane {
@FXML // fx:id="email"
private TextField email; // Value injected by FXMLLoader
public void setEmail(String address) {
this.email.setText(address);
}
}
ManageCtrlTest.java:
public class ManageCtrlTest extends ApplicationTest {
@Override
public void start(Stage stage) {
try {
new Flow(ManageCtrl.class).startInStage(stage);
} catch (FlowException ex) {
Logger.getLogger(ManageCtrlTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Test
public void testSetEmail() {
ManageCtrl instance = new ManageCtrl();
instance.setEmail("test@gmai.com");
assertEquals("test@gmail.com", ((TextField)GuiTest.find("#email")).getText());
}
}
但我得到以下异常:
testSetEmail Failed: java.lang.illegalStateException: Not on FX application thread; currentThread = Test worker
java.lang.illegalStateException: Not on FX application thread; currentThread = Test Worker
感谢您的帮助。
IllegalStateException
与 JavaFX 和 TestFX 的性质有关。
ManageCtrl
从 AnchorPane
扩展,它是 JavaFX 的 Scene
对象之一,所有这些对象都需要在 JavaFX 线程(也称为 JavaFX 应用程序线程或 JavaFX 用户线程)中构建.您可以使用 ApplicationTest#interact
在 JavaFX 线程中构造 ManageCtrl
:
interact(() -> {
ManageCtrl controller = new ManageCtrl();
controller.setEmail("test@gmail.com");
});
然而,这将引发 NullPointerException
,这是由与 new Flow(ManageCtrl.class)
一起使用的 DataFX 的 特性引起的。
new Flow(ManageCtrl.class).startInStage(stage)
将使用您的 @ViewController
中定义的对象注入控制器中所有 @FXML
注释的字段 - new ManageCtrl()
不会。我们可以通过在测试前在字段controller
中构造ManageCtrl
来解决这个问题:
@Override
public void start(Stage stage) throws Exception {
Flow flow = new Flow(ManageCtrl.class);
// create a handler to initialize a view and a sceneRoot.
FlowHandler handler = flow.createHandler();
StackPane sceneRoot = handler.start();
// retrieve the injected controller from the view.
FlowView view = handler.getCurrentView();
controller = (ManageCtrl) view.getViewContext().getController();
// attach the sceneRoot to stage.
stage.setScene(new Scene(sceneRoot));
stage.show();
}
您现在可以使用以下方法测试您的控制器:
@Test
public void should_set_email() throws Exception {
// when:
interact(() -> {
controller.setEmail("test@gmail.com");
});
// then:
verifyThat("#email", hasText("test@gmail.com"));
}
在试图简化这方面测试的 issue on GitHub. I've also created a pull request on Bitbucket 中详细介绍了整个事情。