-
Notifications
You must be signed in to change notification settings - Fork 0
Mocking RPC services
Frequently, your presentation layer will call remote services using GWT-RPC.
In unit tests, you will need to mock the server calls. gwt-test-utils provides an elegant way to do it, using either the EasyMock or the Mockito mocking framework.
Mocking RPC services is much like mocking any other classes, with a few specificities, like asynchronous callback handling.
We will modify the previous sample to use GreetingService
, the sample RemoteService class auto-generated when you create a new Web Application Project.
<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</g:Button>
<g:Label ui:field="label" />
</g:HTMLPanel>
</ui:UiBinder>
public class RpcSampleView extends Composite {
interface RpcSampleViewUiBinder extends UiBinder<Widget, RpcSampleView> { }
private static RpcSampleViewUiBinder uiBinder = GWT.create(RpcSampleViewUiBinder.class);
@UiField
Button button;
@UiField
Label label;
@UiField
TextBox textBox;
private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
public RpcSampleView() {
initWidget(uiBinder.createAndBindUi(this));
label.setVisible(false);
button.setEnabled(false);
}
@UiHandler("button")
void onClick(ClickEvent e) {
greetingService.greetServer(textBox.getText(), new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
label.setText("Server error: " + caught.getMessage());
label.setVisible(true);
}
public void onSuccess(String result) {
label.setText(result);
label.setVisible(true);
}
});
}
@UiHandler("textBox")
void onKeyPress(KeyUpEvent e) {
button.setEnabled(textBox.getText().trim().length() > 0);
label.setVisible(false);
}
}
The GreetingService
servlet implementation is declared in the web.xml
:
<servlet>
<servlet-name>greetServlet</servlet-name>
<servlet-class>com.googlecode.gwt.test.sample.server.GreetingServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>greetServlet</servlet-name>
<url-pattern>/MockSample/greet</url-pattern>
</servlet-mapping>
Clicking the button will make a server call through greetingService.greetServer(...)
. If it goes well, the label would greet him with the text computed server side. Otherwise, the same label would display the thrown error's message.
What we want is testing both cases by mocking the RemoteService call.
- Add the EasyMock maven dependency :
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.0</version>
<scope>test</scope>
</dependency>
-
In order to use the EasyMock mocking framework, your tests need to extend
GwtTestWithEasyMock
. -
Declare your mock RemoteService Async interface using gwt-test-utils's own
@Mock
annotation.
@GwtModule("com.googlecode.gwt.test.sample.MockSample")
public class RpcSampleViewWithEasyMockTest extends GwtTestWithEasyMock {
@Mock
private GreetingServiceAsync greetingServiceAsync;
@Test
public void clickOnButtonShouldDisplayMessageInLabelWhenRpcSuccess() {
// Arrange
RpcSampleView view = new RpcSampleView();
view.textBox.setText("Ben Linus");
view.button.setEnabled(true);
assertThat(view.label).isNotVisible();
// expect service invocation
greetingServiceAsync.greetServer(EasyMock.eq("Ben Linus"), EasyMock.isA(AsyncCallback.class));
expectServiceAndCallbackOnSuccess("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");
}
@Test
public void clickOnButtonShouldDisplayErrorInLabelWhenRpcFailure() {
// Arrange
RpcSampleView view = new RpcSampleView();
view.textBox.setText("Ben Linus");
view.button.setEnabled(true);
assertThat(view.label).isNotVisible();
// expect service invocation
greetingServiceAsync.greetServer(EasyMock.eq("Ben Linus"), EasyMock.isA(AsyncCallback.class));
expectServiceAndCallbackOnFailure(new RuntimeException("expected mocked runtime exception"));
// 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("Server error: expected mocked runtime exception");
}
}
-
@Mock
tells gwt-test-utils to create a mock object using EasyMock. -
expectServiceAndCallbackOnSuccess(Object result)
tells to make the mocked object return the "result" object as a success response to the last call. -
expectServiceAndCallbackOnFailure(Throwable t)
tells to make the mocked object return the "t" exception as a failure response to the last call. -
replay()
will callEasyMock.replay(..)
on each declared@Mock
in the test class. -
verify()
will callEasyMock.verify(..)
on each declared@Mock
in the test class.
- Add the Mockito maven dependency :
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
-
In order to use the Mockito mocking framework, your tests need to extend
GwtTestWithMockito
. -
Declare your mock objets using gwt-test-utils's or Mockito
@Mock
annotation.
@GwtModule("com.googlecode.gwt.test.sample.MockSample")
public class RpcSampleViewWithMockitoTest extends GwtTestWithMockito {
@Mock
private GreetingServiceAsync greetingServiceAsync;
@Test
public void clickOnButtonShouldDisplayMessageInLabelWhenRpcSuccess() {
// Arrange
RpcSampleView view = new RpcSampleView();
view.textBox.setText("Ben Linus");
view.button.setEnabled(true);
assertThat(view.label).isNotVisible();
// mock service succeed invocation
doSuccessCallback("Mocked hello message").when(greetingServiceAsync).greetServer(Mockito.eq("Ben Linus"), Mockito.any(AsyncCallback.class));
// Act
Browser.click(view.button);
// Assert
Mockito.verify(greetingServiceAsync).greetServer(Mockito.eq("Ben Linus"), Mockito.any(AsyncCallback.class));
assertThat(view.label).isVisible().textEquals("Mocked hello message");
}
@Test
public void clickOnButtonShouldDisplayErrorInLabelWhenRpcFailure() {
// Arrange
RpcSampleView view = new RpcSampleView();
view.textBox.setText("Ben Linus");
view.button.setEnabled(true);
assertThat(view.label).isNotVisible();
// mock service failed invocation
doFailureCallback(new RuntimeException("expected mocked runtime exception")).when(greetingServiceAsync).greetServer(Mockito.eq("Ben Linus"), Mockito.any(AsyncCallback.class));
// Act
Browser.click(view.button);
// Assert
Mockito.verify(greetingServiceAsync).greetServer(Mockito.eq("Ben Linus"), Mockito.any(AsyncCallback.class));
assertThat(view.label).isVisible().textEquals("Server error: expected mocked runtime exception");
}
}
-
@Mock
tells gwt-test-utils to create a mock object using Mockito. Both gwt-test-utils or Mockito annotation can be used. -
doSuccessCallback(Object result)
tells to make the mocked object return the "result" object as a success response. -
doFailureCallback(Throwable t)
tells to make the mocked object return the "t" exception as a failure response. -
Mockito.verify(Object mock)
checks thegreetServer()
method was actually called with expected parameters.
Sources of this sample are available here.