Skip to content
Gael Lazzari edited this page Aug 29, 2012 · 13 revisions

In the previous example, we wanted to unit test a GWT view which interacts with the server through a RemoteService. It made sense to mock this service in unit tests, where we wanted to test the view behavior only and explicit its interaction with other objects as much as possible.

But you also may want to test a more complex system, where a lot of class are involved. In such cases, we'll speak about writing integration tests.
gwt-test-utils is perfectly suited for integration testing, where speed is amazing compared to a full-stack system test (browser + Servlet container).

The only downside of using gwt-test-utils for integration tests is you'll have to mock the entire Servlet API. Don't worry, it's quite a simple thing to do ;-)

Integration test sample

To illustrate how to mock the Servlet API, we'll use exactly the same sample application we wrote to illustrate how to mock RPC services.

The only difference will be the test class, which will extend the simple GwtTest instead of one of its "Mock" subtype :

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

  @Test
  public void clickOnButtonShouldDisplayMessageInLabel() {
    // Arrange
    RpcSampleView view = new RpcSampleView();
    view.textBox.setText("Ben Linus");
    view.button.setEnabled(true);
    assertThat(view.label).isNotVisible();
    
    // Act
    Browser.click(view.button);
    
    // Assert
    assertThat(view.label).isVisible().textContains("Hello, Ben Linus!");
  }
  
}

Running this test throws a com.googlecode.gwt.test.exceptions.GwtTestRpcException with message :
"Illegal call to com.googlecode.gwt.test.sample.server.GreetingServiceImpl.getServletConfig() : You have to set a valid ServletMockProvider instance through RpcSampleViewMockingServletTest.setServletMockProvider(..) method"

In GreetingServiceImpl.greetServer(...) implementation, we have those two lines :

String serverInfo = getServletContext().getServerInfo();
String userAgent = getThreadLocalRequest().getHeader("User-Agent");

Like explained earlier, whenever a RemoteService implementation needs an access to the current ServletConfig, HttpServletRequest or HttpServletResponse, you'll need return a mock.

gwt-test-utils provides a ServletMockProvider interface which will be used every time a RemoteServiceServlet implementation calls getThreadLocalRequest(), getThreadLocalResponse() or getServletConfig(). Custom implementations of this interface are setted using the protected setServletMockProvidermethod available in your GwtTest subclasses.

Here is you to setup a simple ServletMockProvider in the RpcSampleViewMockingServletTest class :

@Before
public void before() {

  /** Servlet API mock helpers from gwt-test-utils **/
  private MockServletConfig mockConfig;
  private MockHttpServletRequest mockRequest;
  
  @Before
  public void before() {
    // create the ServletConfig object using gwt-test-utils web mock helper
    MockServletContext context = new MockServletContext();
    context.setServerInfo("mocked-server-info");
    this.mockConfig = new MockServletConfig(context);
    
    // same thing for HttpServletRequest
    this.mockRequest = new MockHttpServletRequest();
    this.mockRequest.addHeader("User-Agent", "mocked-user-agent");
    
    // use the provided adapter to implement only the methods you need for your test
    setServletMockProvider(new ServletMockProviderAdapter() {
    
      @Override
      public ServletConfig getMockedConfig(AbstractRemoteServiceServlet remoteService) {
        return mockConfig;
      }
      
      @Override
      public HttpServletRequest getMockedRequest(AbstractRemoteServiceServlet rpcService, Method rpcMethod) {
        return mockRequest;
      }
    });
  }
  
}

With this configuration, you can safely expect that:

getServletContext().getServerInfo(); // always returns "mocked-server-info"
getThreadLocalRequest().getHeader("User-Agent"); // always returns "mocked-user-agent"

Note: gwt-test-utils comes with a set of mock implementations for most servlet API objects you may want to use to build your mocks: MockHttpServletRequest, MockHttpServletResponse, MockHttpSession, MockServletConfig, MockServletContext, MockRequestDispatcher.

Now that you have mocked serverInfo and userAgent data, you know exactly what should be displayed in the label. Change the assertions part of your unit test which was :

assertThat(view.label).isVisible().textContains("Hello, Ben Linus!");

to :

assertThat(view.label).isVisible().textEquals("Hello, Ben Linus!<br><br>I am running mocked-server-info.<br><br>It looks like you are using:<br>mocked-user-agent");

Sources of this sample are available here.