Reflected Circle

Reflected Circle

Its just a name

Reflected Circle RSS Feed
 
 
 
 

GWT RPC AsyncCallback testing using Mockito

Been working with GWT a lot recently. MVP allows easier unit testing of the client logic, but those asynchronous RPC callbacks are usually implemented as anonymous inner classes which are a bitch to test.

However, they can be mocked out and tested with a custom stubber like this.

   public static class AsyncMockStubber {
        private static <T> Stubber callSuccessWith(final T data) {
            return Mockito.doAnswer(new Answer<T>() {
                @Override
                @SuppressWarnings("unchecked")
                public T answer(InvocationOnMock invocationOnMock) throws Throwable {
                    final Object[] args = invocationOnMock.getArguments();
                    ((AsyncCallback) args[args.length - 1]).onSuccess(data);
                    return null;
                }
            });
        }
    }

Its nice that the async interface always has the callback as the last parameter, so one size fits all.

    AsyncMockStubber.callSuccessWith(data).when(armorService).getData(any(AsyncCallback.class));

7 Responses to “GWT RPC AsyncCallback testing using Mockito”

  1. 1
    Chuck Irvine:

    Hello Tim, I started learning Mockito an hour or so ago and I want to apply your code above to testing my GWT activities (presenters). However, I’m having trouble understanding the context in which you use your call to “syncMockStubber.callSuccessWith(data)…”. Would it be possible to provide a line or two of sample code that would proceed and follow this line of code? Thanks, Chuck

  2. 2
    Tim:

    Hi Chuck,

    I’m trying to test the behaviour of the class with an AsyncCallback which is often an anonymous inner class like this example from a presenter method:

            service.getData(new  AsyncCallback<Data>() {
                @Override
                public void onFailure(Throwable throwable) {
                    // do something bad with throwable
                }
    
                @Override
                public void onSuccess(Data data) {
                    // do something good with data
                }
            } );
    

    Typically, onSuccess() will either call to update the display or fire an event.

    You’ll have the async service setup to mirror your server side service

       public interface ServiceAsync {
           void getData(AsyncCallback<Data> callback);
           void updateData(String param1, String param2, AsyncCallback<Data> callback);
       }
    

    The test might look something like this:

        ServiceAsync service = Mockito.mock(ServiceAsync.class);      
       
        Data data = new Data(); // expected response from server side service.
    
        AsyncMockStubber.callSuccessWith(data).when(service).getData(any(AsyncCallback.class));
    
        presenter.onBind();
    
        assertThat(something, equalTo(expected));
    

    ..will simulate that any call to the service.getData() will invoke onSuccess() so you can test the behaviour of the whole method with a successful async response. A similar stubber can be made for the onFailure() method.

  3. 3
    GWT Testing « GWT Buzz:

    […] http://blog.reflectedcircle.com/2009/12/08/gwt-rpc-asynccallback-testing-using-mockito/ […]

  4. 4
    Yogesh:

    Hi Tim,
    I am trying to write a test case using Mockito for the sample code that GWT generates(GreetingServiceAsync.java and I am using Eclipse Helios). I tried the code snippet you have shared here. For some reason it is not recognizing the method “any(AsyncCallBack.class)”.
    If possible could you mail me the code so that I can understand what exactly Mockito is trying to do? It would be really helpful.

    Thanks,
    Yogesh

  5. 5
    Tim:

    Hi Yogesh,

    I don’t have the code this was derived from, it was based on a project at work, so classes and variable names have been changed to protect the innocent.

    The any() method is one of the Mockito Matchers.

    I suspect the issue is that when one parameter is a matcher, then all the parameters should be matchers also. If they are actual objects, then just wrap them in the eq() matcher.

    e.g.

        AsyncMockStubber.callSuccessWith(data).when(greetingService).greetServer(eq(aPerson), any(AsyncCallback.class));
    
  6. 6
    David:

    @Yogesh

    I hope this is not too late but for this issue:

    | For some reason it is not recognizing the method “any(AsyncCallBack.class)”.

    You need to,

    import static org.mockito.Mockito.any;

  7. 7
    Askari:

    @David,@Yogesh
    you need import static org.mockito.Matchers.any;

Leave a Reply