GwtMockito

Better GWT unit testing

This project is maintained by google

What is GwtMockito?

Testing GWT applications using GWTTestCase can be a pain - it's slower than using pure Java tests, and you can't use reflection-based tools like mocking frameworks. But if you've tried to test widgets using normal test cases, you've probably run into this error:

ERROR: GWT.create() is only usable in client code!  It cannot be called,
for example, from server code. If you are running a unit test, check that 
your test case extends GWTTestCase and that GWT.create() is not called
from within an initializer or constructor.

GwtMockito solves this and other GWT-related testing problems by allowing you to call GWT.create from JUnit tests, returning Mockito mocks.

How do I use it?

Getting started with GwtMockito using Junit 4.5+ is easy. Just annotate your test with @RunWith(GwtMockitoTestRunner.class), then any calls to GWT.create encountered will return Mockito mocks instead of throwing exceptions:

@RunWith(GwtMockitoTestRunner.class)
public class MyTest {
  @Test
  public void shouldReturnMocksFromGwtCreate() {
    Label myLabel = GWT.create(Label.class);
    when(myLabel.getText()).thenReturn("some text");
    assertEquals("some text", myLabel.getText());
  }
}

GwtMockito also creates fake implementations of all UiBinders that automatically populate @UiFields with Mockito mocks. Suppose you have a widget that looks like this:

public class MyWidget extends Composite {
  interface MyUiBinder extends UiBinder<Widget, MyWidget> {}
  private final MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

  @UiField Label numberLabel;
  private final NumberFormatter formatter;

  public MyWidget(NumberFormatter formatter) {
    this.formatter = formatter;
    initWidget(uiBinder.createAndBindUi(this);
  }

  void setNumber(int number) {
    numberLabel.setText(formatter.format(number));
  }
}

When createAndBindUi is called, GwtMockito will automatically populate numberLabel with a mock object. Since @UiFields are package-visible, they can be read from your unit tests, which lets you test this widget as follows:

@RunWith(GwtMockitoTestRunner.class)
public class MyWidgetTest {

  @Mock NumberFormatter formatter;
  private MyWidget widget;

  @Before
  public void setUp() {
    widget = new MyWidget(formatter);
  }

  @Test
  public void shouldFormatNumber() {
    when(formatter.format(5)).thenReturn("5.00");
    widget.setNumber(5);
    verify(widget.numberLabel).setText("5.00");
  }
}

Note that GwtMockito supports the @Mock annotation from Mockito, allowing standard Mockito mocks to be mixed with mocks created by GwtMockito.

That's all you need to know to get started - read on if you're interested in hearing about some advanced features.

Accessing the mock returned from GWT.create

Returning mocks from GWT.create isn't very useful if you don't have any way to verify or set behaviors on them. You can do this by annotating a field in your test with @GwtMock - this will cause all calls to GWT.create for that type to return a mock stored in that field, allowing you to reference it in your test. So if you have a class that looks like

public class MyClass {
  public MyClass() {
    SomeInterface myInterface = GWT.create(SomeInterface.class);
    myInterface.setSomething(true);
  }
}

then you can verify that it works correctly by writing a test that looks like this:

@RunWith(GwtMockitoTestRunner.class)
public class MyClassTest {
  @GwtMock SomeInterface mockInterface;

  @Test
  public void constructorShouldSetSomething() {
    new MyClass();
    verify(mockInterface).setSomething(true);
  }
}

Returning fake objects

By default, GwtMockito will return fake implementations (which don't require you to specify mock behavior) for any classes extending the following types:

You can add fakes for additional types by invoking GwtMockito.useProviderForType(Class, FakeProvider) in your setUp method. This will cause all calls to GWT.create for the given class or its subclasses to invoke the given FakeProvider to determine what to return. See the javadoc reference for more details.

Mocking final classes and methods

Mockito does not normally allow final classes and methods to be mocked. This poses problems in GWT since JavaScript overlay types (which include Element and its subclasses) require all methods to be final. Fortunately, GwtMockito does some classloader black magic to remove all final modifiers from classes and interfaces, so the following test will pass:

@RunWith(GwtMockitoTestRunner.class)
public class MyTest {
  @Mock Element element;

  @Test
  public void shouldReturnMocksFromGwtCreate() {
    when(element.getClassName()).thenReturn("mockClass");
    assertEquals("mockClass", myLabel.getClassName());
  }
}

As long as your test uses GwtMockitoTestRunner, it is possible to mock any final methods.

Dealing with native methods

Under normal circumstances, JUnit tests will fail with an UnsatisfiedLinkError when encountering a native JSNI method. GwtMockito works around this problem using more classloader black magic to provide no-op implementations for all native methods using the following rules:

These rules allow many tests to continue to work even when calling incindental native methods. Note that this can be dangerous - a JSNI method that normally always returns true would always return false when stubbed by GwtMockito. As much as possible, you should isolate code that depends on JSNI into its own class, inject that class into yours, and test the factored-out class using GWTTestCase.

Support for JUnit 3 and other tests that can't use custom runners

Though GwtMockitoTestRunner is the easiest way to use GwtMockito, it won't work if you're using JUnit 3 or rely on another custom test runner. In these situations, you can still get most of the benefit of GwtMockito by calling GwtMockito.initMocks directly. A test written in this style looks like this:

public class MyWidgetTest extends TestCase {

  private MyWidget widget;

  @Override
  public void setUp() {
    super.setUp();
    GwtMockito.initMocks(this);
    widget = new MyWidget() {
      protected void initWidget(Widget w) {
        // Disarm for testing
      }
    };
  }

  @Override
  public void tearDown() {
    super.tearDown();
    GwtMockito.tearDown();
  }

  public void testSomething() {
    // Test code goes here
  }
}

The test must explicitly call initMocks during its setup and tearDown when it is being teared down, or else state can leak between tests. When instantiating a widget, the test must also subclass it and override initWidget with a no-op implementation, or else it will fail when this method attempts to call Javascript. Note that when testing in this way the features described in "Mocking final classes and methods" and "Dealing with native methods" won't work - there is no way to mock final methods or automatically replace native methods without using GwtMockitoTestRunner.

How do I install it?

If you're using Maven, you can add the following to your <dependencies> section:

<dependency>
  <groupId>com.google.gwt.gwtmockito</groupId>
  <artifactId>gwtmockito</artifactId>
  <version>1.1.6</version>
  <scope>test</scope>
</dependency>

You can also download the jar directly or check out the source using git from https://github.com/google/gwtmockito.git. In these cases you will have to manually install the jars for Mockito and Javassist.

Where can I learn more?

Version history

1.1.6

1.1.5

1.1.4

1.1.3

1.1.2

1.1.1

1.1.0

1.0.0