如何测试JavaFX控制器的方法?

如何测试JavaFX控制器的方法?,java,unit-testing,javafx-8,Java,Unit Testing,Javafx 8,我试图使用TestFX来测试我的应用程序。我想运行控制器方法的测试 Main.java: public类主扩展应用程序{ 试一试{ 新流(ManageCtrl.class).startInStage(primaryStage); }捕获(例外情况除外){ LOGGER.log(Level.SEVERE,null,ex); } } ManageCtrl.java: @ViewController(“/FPManage.fxml”) 公共类ManageCtrl扩展AnchorPane{ @FXML

我试图使用TestFX来测试我的应用程序。我想运行控制器方法的测试

Main.java:

public类主扩展应用程序{
试一试{
新流(ManageCtrl.class).startInStage(primaryStage);
}捕获(例外情况除外){
LOGGER.log(Level.SEVERE,null,ex);
}
}
ManageCtrl.java:

@ViewController(“/FPManage.fxml”)
公共类ManageCtrl扩展AnchorPane{
@FXML//fx:id=“电子邮件”
private TextField email;//FXMLLoader注入的值
公共无效设置电子邮件(字符串地址){
this.email.setText(地址);
}
}
ManageCtrlTest.java:

public类ManageCtrlTest扩展了ApplicationTest{
@凌驾
公众假期开始(阶段){
试一试{
新流程(ManageCtrl.class).startInStage(stage);
}捕获(FlowException-ex){
Logger.getLogger(ManageCtrlTest.class.getName()).log(Level.SEVERE,null,ex);
}
}
@试验
public void testSetEmail(){
ManageCtrl实例=新的ManageCtrl();
实例。setEmail(“test@gmai.com");
资产质量(”test@gmail.com“,((TextField)GuiTest.find(#email”).getText();
}
}
但我有以下例外:

testSetEmail失败:java.lang.illegalStateException:不在FX应用程序线程上;currentThread=测试工作线程
java.lang.illegalStateException:不在FX应用程序线程上;currentThread=测试工作线程

感谢您的帮助。

非法状态异常与JavaFX和TestFX的性质有关

ManageCtrl
扩展自
AnchorPane
,它是JavaFX的
Scene
对象之一,所有这些对象都需要在JavaFX线程(也称为JavaFX应用程序线程或JavaFX用户线程)中构造。您可以使用
ApplicationTest#interact
在JavaFX线程中构造
ManageCtrl

interact(() -> {
    ManageCtrl controller = new ManageCtrl();
    controller.setEmail("test@gmail.com");
});
但是,这将引发一个
NullPointerException
,这是由与
新流(ManageCtrl.class)
一起使用的DataFX的性质引起的

newflow(ManageCtrl.class)。startInStage(stage)
将使用在
@ViewController
-
newmanagectrl()
中定义的对象在控制器中注入所有
@FXML
-注释字段。我们可以通过在测试前将
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"));
}


整件事在一份报告中详细说明。我还创建了一个简化测试的框架。

我从未使用过TestFX,因此可能有一个特定的解决方案用于该框架。安迪·蒂尔创作了一部电影。也许您可以根据自己的目的对其进行调整,尽管我希望一个名为TestFX的框架能够以本机方式处理这些事情。但我从作者那里得到了答案:。要点是使用DataFXAPI:
Flow Flow=newflow(ManageCtrl.class);FlowHandler=flow.createHandler();stage.setScene(新场景(handler.start());stage.show();FlowView=handler.getCurrentView();控制器=(ManageCtrl)view.getViewContext().getController()使用该控制器,我们可以在内部调用方法。5分钟太短,我无法预览结果<代码>流=新流(ManageCtrl.class)仍然无法添加换行符,但帮助说明添加2个空格将添加
。也未能添加高亮语法。您可以将其标记为正确。我建议您通过总结场外信息来做到这一点(因此答案是自包含的堆栈溢出)。这比在评论中发布代码要好。