Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing GWTP presenter with asynchronous calls

I'm using GWTP, adding a Contract layer to abstract the knowledge between Presenter and View, and I'm pretty satisfied of the result with GWTP. I'm testing my presenters with Mockito.

But as time passed, I found it was hard to maintain a clean presenter with its tests. There are some refactoring stuff I did to improve that, but I was still not satisfied.

I found the following to be the heart of the matter : My presenters need often asynchronous call, or generally call to objects method with a callback to continue my presenter flow (they are usually nested).

For example :

  this.populationManager.populate(new PopulationCallback()
  {
     public void onPopulate()
     {
        doSomeStufWithTheView(populationManager.get());
     }
  });

In my tests, I ended to verify the population() call of the mocked PopulationManager object. Then to create another test on the doSomeStufWithTheView() method.

But I discovered rather quickly that it was bad design : any change or refactoring ended to broke a lot of my tests, and forced me to create from start others, even though the presenter functionality did not change ! Plus I didn't test if the callback was effectively what I wanted.

So I tried to use mockito doAnswer method to do not break my presenter testing flow :

doAnswer(new Answer(){
     public Object answer(InvocationOnMock invocation) throws Throwable
     {
        Object[] args = invocation.getArguments();
        ((PopulationCallback)args[0]).onPopulate();
        return null;
     }
 }).when(this.populationManager).populate(any(PopulationCallback.class));

I factored the code for it to be less verbose (and internally less dependant to the arg position) :

doAnswer(new PopulationCallbackAnswer())
  .when(this.populationManager).populate(any(PopulationCallback.class));

So while mocking the populationManager, I could still test the flow of my presenter, basically like that :

@Test
public void testSomeStuffAppends()
{
  // Given
  doAnswer(new PopulationCallbackAnswer())
  .when(this.populationManager).populate(any(PopulationCallback.class));

  // When
  this.myPresenter.onReset();

  // Then
  verify(populationManager).populate(any(PopulationCallback.class)); // That was before
  verify(this.myView).displaySomething(); // Now I can do that.
}

I am wondering if it is a good use of the doAnswer method, or if it is a code smell, and a better design can be used ?

Usually, my presenters tend to just use others object (like some Mediator Pattern) and interact with the view. I have some presenter with several hundred (~400) lines of code.

Again, is it a proof of bad design, or is it normal for a presenter to be verbose (because its using others objects) ?

Does anyone heard of some project which uses GWTP and tests its presenter cleanly ?

I hope I explained in a comprehensive way.

Thank you in advance.

PS : I'm pretty new to Stack Overflow, plus my English is still lacking, if my question needs something to be improved, please tell me.

like image 235
Antonin M. Avatar asked Dec 06 '12 10:12

Antonin M.


Video Answer


1 Answers

You could use ArgumentCaptor:
Check out this blog post fore more details.

like image 71
Ümit Avatar answered Oct 20 '22 00:10

Ümit