JUnit Tests with Eclipse Databinding

Written July 14th, 2011 by

When we started to use Eclipse Databinding framework we faced the problem of running JUnit tests against databinding-enabled classes. Databinding requires a default Realm to be defined and all classes must be run from within this realm. The Eclipse framework automatically initializes the default realm at application startup with a code that looks like the following (from Workbench.createAndRunWorkbench):

    Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
        public void run() {
            ULocale.setDefault(new ULocale(Platform.getNL()
                    + Platform.getNLExtensions()));
            // create the workbench instance
            Workbench workbench = new Workbench(display, advisor);
            // run the workbench event loop
            returnCode[0] = workbench.runUI();
        }
    });

 

JUnit allows to override the method used to run all tests defined in a class allowing us to add the code to initialize the default Realm like the above. Following are the two classes we are using to run JUnit tests against databinding-enabled classes.

 

JUnit 3

We wrote a DatabindingTestCase class derived from the original TestCase and overrode the run method to add the code to wrap the default realm, test case classes are then derived from DatabindingTestCase instead of TestCase.

import junit.framework.TestCase;
import junit.framework.TestResult;

import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.swt.widgets.Display;

public class DatabindingTestCase extends TestCase {

    public DatabindingTestCase() {
    }

    public DatabindingTestCase(String name) {
        super(name);
    }

    @Override
    public void run(final TestResult result) {
        Display display = Display.getDefault();
        Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {

            @Override
            public void run() {
                DatabindingTestCase.super.run(result);
            }
        });
    }

    public void testEmpty() throws Exception {
        // To keep JUnit happy
    }
}

 

JUnit 4

A bit more complicated because it uses annotations and test cases aren’t derived from a base class. In this case we wrote a replacement class runner DatabindingClassRunner  and overrode the run method, just like we did for JUnit 3, test case classes are then annotated with @RunWith(DatabindingClassRunner.class).

import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.swt.widgets.Display;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;

public class DatabindingClassRunner extends BlockJUnit4ClassRunner {

    public DatabindingClassRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    public void run(final RunNotifier notifier) {
        Display display = Display.getDefault();
        Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {

            @Override
            public void run() {
                DatabindingClassRunner.super.run(notifier);
            }
        });
    }
}

 

Links:

http://wiki.eclipse.org/index.php/JFace_Data_Binding

http://www.junit.org/