[SOLVED] Javafx issue with field injection in junit test

OK, I am hitting a wall, and am hoping someone has an idea.
I have built integration tests for my server and client. They work great except for my fxml controllers.
Running the client outside of the junit5 test works fine with no issues, all fields in my controller get injected. But when running in my junit5 test the UI loads just fine in jme like I would expect, but all injected fields are null in the controller. The FXMLLoader does see the controller, and even runs the initialize() function. There are no exceptions throw (except for the NPE from the fields not being injected).

Any thoughts?

This is how I am creating my controllers. It works fine when running the app like normal:

private Object getController() throws Exception {
        ScriptEngine scripts = engine.getWorld().getOutside().getEngines().getComponent(ScriptEngine.class);
        Class controllerClass = scripts.load(controller);
        if (controllerClass == null) {
            LOGGER.warning("Failed to load controller " + controller + " for " + name);
            return null;
        }
        return controllerClass.getConstructor(GuiEngine.class).newInstance(engine);
    }

@Override
    public void buildUI() {
        try {
            loader = new FXMLLoader(new File(fxmlFile).toURI().toURL());

            try {
                control = (control == null ? getController() : control); //If we have a control, we will use it...
                if (control != null) {
                    loader.setController(control);
                } else {
                    Logger.getLogger(Outside.class.getName()).info("No script controller found");
                }
            } catch (Exception ex) {
                Logger.getLogger(Outside.class.getName()).log(Level.SEVERE, null, ex);
            }

            Node parent = loader.load();
            this.rootNode = new Group(parent);

            if (control instanceof FXMLController) {
                ((FXMLController) control).load();
                //Check if we are already enabled, in which case run show
                if (this.isEnabled()) {
                    ((FXMLController) control).show();
                }
            }

        } catch (Exception ex) {
            Logger.getLogger(Outside.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

(Sorry, a lot of black magic in this code from things that the engine handles in the background)

For the next person who runs into this. The thing that broke it was not what I expected.
After many hours and several test projects where I could not replicate the issue. The problem came down to using testImplementation("com.ginsberg:junit5-system-exit:1.0.0") to get the @ExpectSystemExit annotation in my tests. Apparently something with that annotation explicitly breaks field injection with javafx to groovy scripts, and no other field injection or reflection access I perform.

1 Like