Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Presenters in MVP GWT application

I have a simple application and want to make it testable. I m new in this area. Here is a simple Presenter, taking in mind this code ,could you advice or give me some example how to test it.

    public class SomePresenter extends Presenter<MainPanelPresenter.Display>
    {

    public interface Display extends WidgetDisplay
    {
      HasClickHandlers getAddButton();

      HasClickHandlers getDeleteButton();

      void setData(ArrayList<Person> data);

      ArrayList<String> getSelectedRows();

      Widget asWidget();

    }

    private final DispatchAsync dispatcher;
    public static final Place PLACE = new Place("main");

    @Inject
    public SomePresenter(DispatchAsync dispatcher, EventBus eventBus, Display display)
    {
      super(display, eventBus);
      this.dispatcher = dispatcher;
      bind();
    }

    protected void onBind()
    {
      display.getAddButton().addClickHandler(new ClickHandler()
      {
        public void onClick(ClickEvent event)
        {
          eventBus.fireEvent(new AddButtonEvent());
        }
      });

      display.getDeleteButton().addClickHandler(new ClickHandler()
      {
        public void onClick(ClickEvent event)
        {
          ArrayList<String> list = display.getSelectedRows();
          deletePerson(list);
        }
      });
    }
    ....
    private void loadDbData()
    {
     ..........
    }
    private void deletePerson(ArrayList<String> ids)
    {
     ..........
     }
   }

Edit:

What does the Presenter is, load initial data from db, have 2 buttons add and delete. When add is press then a new form is load and user is able to input data and save to the db, delete button just delete person from db.

Thanks

like image 545
adgfs Avatar asked Jul 07 '11 14:07

adgfs


1 Answers

The general idea of unit testing such a class would be, like for any other class :

  • create Mock version of the dependencies (Display, EventBus, etc...)
  • set expectations on what the depdencies should do when the Presenter works
  • exercice the Presenter and check the expectations

However there are a couple of issues with your version of the Presenter :

  • The loadDbData() method is not showed, but I assumed it means the Presenter also has access to some other component that does the fetching. Can this component be abtracted in a dependency, and mocked liked the rest ?

  • Then there is the testing of bind(). The only responsibility of your Presenter in this method is to set up callbacks on some buttons provided by the Display. What you want to test is both :

    • That the callbacks are set
    • That the set callbacks do the expected things

A few ideas to help with the later :

You can reduce the coupling between Presenter and Button. If possible, change the Display interface from :

Button getAddButton();

to

addAddButtonClickedHandler(ClickHandler);

This means your Presenter does not have to use a Display object that returns actual BUtton

You can reduce the callbacks content to calling a single method, that you can then test in isolation

protected void bind() {
   display.addAddButtonClickHandler(new ClickHandler() {
       public void onClick(ClickEvent) {
          fireAdded();
       } 
   });
} 

// The fireAdded function can be tested independenty of the Display, potentially with 
// a mock EventBus
protected void fireAdded() {
   event.fireEvent(....)
}

If you really want to check that the callbacks are properly set, than you can use a 'Dummy' implementation of the Display class, that provides you a list of all the callbacks, and let you call them

private class DummyDisplay implements Display  {

   private List<ClickHandler> addButtonClickHandlers;
   public void addAddButtonClickHandler(ClickHandler handler) {
       addButtonClickHandlers.add(handler);
   }
   public void fireAddButtonClick() {
       for (ClickHandler h in addButtonClickHandlers) {
              h.onClick(new ClickEvent());
       }
   }
   // .... 
}

Then your test would :

  • create a presenter with such a dummy display
  • use bind to set the callbacks
  • use display.fireAddButtonClick() to simulate a user clicking
  • check that has the result of the click, the effects of fireAdded are seen

This type of class (that mostly glue other classes together) can tend to be hard to test ; at some point, it the other classes are thoroughly tested it can become slightly counter productive to concentrate on the gluers, rather than the glued.

Hoping this helps.

like image 155
phtrivier Avatar answered Sep 28 '22 21:09

phtrivier