-
Notifications
You must be signed in to change notification settings - Fork 0
Mocking Servlets
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 ;-)
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 setServletMockProvider
method 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.