Skip to content

Testing with TestFX

Manuel Mauky edited this page Jul 6, 2015 · 6 revisions

Testing with TestFX

TestFX is a library for intergration testing of JavaFX applications and components. It provides an API for "interacting with, and verifying the behavior of, JavaFX applications". This wiki page shows you how to test mvvmFX applications or components with TestFX.

As TestFX tests are integration tests you need to take care when you are using a dependency injection framework together with mvvmFX.

mvvmFX View without Dependency Injection

public class MyTest extends GuiTest {
    @Override
    public Parent getRootNode(){
        return FluentViewLoader.fxmlView(MyView.class).load().getView();
    }

    @Test
    public void test_should_this_and_that(){
        click(".button");
        ...
    }
}

mvvmFX View with Dependency Injection setup in the test

This can be seen in the books-example. It uses EasyDI as dependency injection library.

public class MyTest extends GuiTest {
    @Override
    public Parent getRootNode(){
        EasyDi context = new EasyDI(); // setup DI library
        MvvmFX.setCustomDependencyInjector(context::getInstance);  // tell mvvmFX which DI library to use.
        return FluentViewLoader.fxmlView(MyView.class).load().getView();
    }

    @Test
    public void test_should_this_and_that(){
        click(".button");
        ...
    }
}

mvvmFX application with CDI/Guice

When using the mvvmfx-cdi or mvvmfx-guice package for your application, the setup of the dependency injection framework is done in a special application class. For testing the application with TestFX you need to configure the TestFX testrunner to use your application class instead of creating one on its own. This is only possible in newer beta releases of TestFX. In the contacts-example we have an example TestFX test case that uses the 4.0.0-SNAPSHOT version of TestFX.

public class MyTest extends FxRobot {
    @Before
    public void setupApp() throws Exception{
        FxToolkit.registerPrimaryStage();

        // App.class is your application class that extends de.saxsys.mvvmfx.cdi.MvvmfxCdiApplication
        FxToolkit.setupApplication(App.class); 
    }

    @Test
    public void test_should_this_and_that(){
        clickOn(".button");
        ...
    }
}

Unittest vs. Integrationtest

In the description at the start of this wiki page I said that TestFX is used for "integration testing". Lets clearify some terms from the context of testing: In an integration test the developer want's to verify that her components are playing nicely together and that the "integration" in the environment of the component is working as expected. With TestFX you verify that your component is working nicely together with the JavaFX framwork.

In a "unit test" instead you are testing your component in isolation. Given that everything else is working as expected, how does your component behave?

Both unit tests and integration tests are important but they both have specific advantages and disadvantages too. For example integration tests are slowly most of the time compared to unit tests because staring up the application environment takes some time and resources.

One of the main goals of developing mvvmFX was to be able to reduce the amount of integration tests needed and to be able to test as much of your UI with unit tests as possible. This is archived by placing all UI logic inside the ViewModels and the ViewModels are simple classes that can be tested without a running JavaFX environment. Nevertheless there are still many situations where you need integration tests and TestFX is a great tool for this.