Skip to content
Gael Lazzari edited this page Aug 27, 2012 · 15 revisions

Sometimes, you may be writing unit tests for a class that has dependencies to other classes, and that interact with them via method calls. In this case, you might want to use mock objets instead of real objects for these classes : they allow you to test that the right method calls were made, instead of testing the actual behavior of the objects.

gwt-test-utils allows you to write unit tests that use mock objects, using either the EasyMock or the Mockito mocking framework.

Mocking support consists in three main features :

  • Obtaining mock objets when using deferred binding : when declaring mock objects in your test class, you're telling gwt-test-utils that GWT.create(Class clazz) deferred binding made in your application code should return the mock object of the corresponding type, declared in test class.
  • RPC calls/callbacks stubbing : shortcut methods that ease the mocking of RPC calls and the handling of callbacks in tests.
  • Helper methods : a few methods to ease some mocking operations, particularly when using EasyMock.

Our application code

We will modify the previous sample to use an external ClientGreetingobject to say hello.

MockSampleView.ui.xml :

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
  xmlns:g="urn:import:com.google.gwt.user.client.ui">
	<g:HTMLPanel>
		<g:TextBox ui:field="textBox"></g:TextBox>
		<g:Button ui:field="button">Say Hello RPC</g:Button>
		<g:Label ui:field="label" />
	</g:HTMLPanel>
</ui:UiBinder> 

MockSampleView.java :

public class MockSampleView extends Composite {

  interface MockSampleViewUiBinder extends UiBinder<Widget, MockSampleView> { }
  
  private static MockSampleViewUiBinder uiBinder = GWT.create(MockSampleViewUiBinder.class);
  
  @UiField
  Button button;
  
  @UiField
  Label label;
  
  @UiField
  TextBox textBox;
  
  private final ClientGreeting clientGreeting;
  
  public MockSampleView(ClientGreeting clientGreeting) {
    this.clientGreeting = clientGreeting;
    initWidget(uiBinder.createAndBindUi(this));
    label.setVisible(false);
    button.setEnabled(false);
  }
  
  @UiHandler("button")
  void onClick(ClickEvent e) {
    label.setText(clientGreeting.greet(textBox.getText()));
    label.setVisible(true);
  }
  
  @UiHandler("textBox")
  void onKeyPress(KeyUpEvent e) {
    button.setEnabled(textBox.getText().trim().length() > 0);
    label.setVisible(false);
  }
  
}

ClientGreeting.java :

public class ClientGreeting {
  
  public String greet(String name) {
    return "ClientGreeting says hello " + name;
  }
  
}

Using EasyMock

  1. Add the EasyMock maven dependency :
<dependency>
  <groupId>org.easymock</groupId>
  <artifactId>easymock</artifactId>
  <version>3.0</version>
  <scope>test</scope>
</dependency>
  1. In order to use the EasyMock mocking framework, your tests need to extend GwtTestWithEasyMock.

  2. Declare your mock objets using gwt-test-utils's own @Mock annotation.

@GwtModule("com.googlecode.gwt.test.sample.MockSample")
public class MockSampleViewWithEasyMockTest extends GwtTestWithEasyMock {

  @Mock
  private ClientGreeting clientGreeting;
  
  @Test
  public void clickOnButtonShouldDisplayMessageInLabel() {
    // Arrange
    MockSampleView view = new MockSampleView(clientGreeting);
    view.textBox.setText("Ben Linus");
    view.button.setEnabled(true);
    assertThat(view.label).isNotVisible();
    
    // expect object invocation
    EasyMock.expect(clientGreeting.greet(EasyMock.eq("Ben Linus"))).andReturn("Mocked hello message");
    
    // EasyMock.replay(..) for every @Mock objects
    replay();
    
    // Act
    Browser.click(view.button);
    
    // Assert
    // EasyMock.verify(..) for every @Mock objects
    verify();
    assertThat(view.label).isVisible().textEquals("Mocked hello message");
  }

}
  • @Mock tells gwt-test-utils to create a mock object using EasyMock.

  • replay() will call EasyMock.replay(..) on each declared @Mock in the test class.

  • verify() will call EasyMock.verify(..) on each declared @Mock in the test class.

Of course, you can also use the EasyMock API rather than methods provided by GwtTestWithEasyMock.

Warning : mock objects not declared using the @Mock annotation (e.g. objects instantiated by calling directly the EasyMock.createMock() method) should be added to the test context using the GwtTestWithMocks#addMockedObject() method.

Using Mockito

  1. Add the Mockito maven dependency :
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>1.8.5</version>
  <scope>test</scope>
</dependency>
  1. In order to use the Mockito mocking framework, your tests need to extend GwtTestWithMockito.

  2. Declare your mock objets using gwt-test-utils's or Mockito @Mock annotation.

@GwtModule("com.googlecode.gwt.test.sample.MockSample")
public class MockSampleViewWithMockitoTest extends GwtTestWithMockito {

  @Mock
  private ClientGreeting clientGreeting;
  
  @Test
  public void clickOnButtonShouldDisplayMessageInLabel() {
    // Arrange
    MockSampleView view = new MockSampleView(clientGreeting);
    view.textBox.setText("Ben Linus");
    view.button.setEnabled(true);
    assertThat(view.label).isNotVisible();
    
    // expect object invocation
    Mockito.when(clientGreeting.greet(Mockito.eq("Ben Linus"))).thenReturn("Mocked hello message");
    
    // Act
    Browser.click(view.button);
    
    // Assert
    Mockito.verify(clientGreeting).greet(Mockito.eq("Ben Linus"));
    assertThat(view.label).isVisible().textEquals("Mocked hello message");
  }
   
}
  • @Mock tells gwt-test-utils to create a mock object using Mockito. Both gwt-test-utils or Mockito annotation can be used.

  • Mockito.verify(Object mock) checks the greet() method was actually called with expected parameters.

Warning : mock objects not declared using the @Mock annotation (e.g. objects instantiated by calling directly the Mockito.mock() method) should be added to the test context using the GwtTestWithMocks#addMockedObject() method.

Sources of this sample are available here.