我试图使用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
感谢您的帮助。
答案 0 :(得分:1)
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)
会在控制器中注入所有@FXML
个带注释的字段,而@ViewController
- new ManageCtrl()
中定义的对象则不会。我们可以通过在测试前将ManageCtrl
构建到字段controller
来解决此问题:
@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中有详细说明。我还创建了一个pull request on Bitbucket,试图简化这方面的测试。