How to do a right unit test for the Presenter in MVP

121 Views Asked by At

I'm using the MVP pattern. And faced with a problem of covering the Presenter with unit testing.

Behavior: View(Form) has two buttons on it - Ok and Apply.

If Ok button is pressed then the Data must be validated and in a case of success the Data must be saved and View must be closed.

If Apply button is pressed then the Data must be validated and in a case of success the Data must be saved then the Data must be reloaded and the View must be refreshed.

Presenter has two methods which are called by the View in case of Ok and Apply buttons are pressed. They are OkButtonPressed and ApllyButtonPressed respectively.

This is a pseudo code of the Presenter

private
  // view intreface
  View : IView; 
  function TrySaveChanges: boolean {
    //Validate data by calling Model's methods
    //Save data by calling Model's methods
    // In case of any error call View to show an error message
  }      
  function RefreshData: boolean {
    //Load data by calling Model's methods
  };
  function RefershView: boolean {
    //Call View's methods to refresh the data on it
  };

public
  procedure OkButtonPressed {
    if TrySaveChanges {
      View.Close;
    }
  }
  procedure ApplyButtonPressed {
    If TrySaveChanges {
      RefreshData;
      RefershView;
    }  
  }

How cover such code with unit test? Roy Osherove says to test public methods as public methods call private ones. So via tests for public the behavior of private can be tested. But in the example above few Presenter's public methods call the same private method. What should exact be tested for the OkButtonPressed and ApplyButtonPressed methods? Regarding to Roy behavior of TrySaveChanges must be tested in tests for OkButtonPressed and ApplyButtonPressed methods. But will this produce tests "duplicates"? If I do not test the TrySaveChanges methods behavior in tests for OkButtonPressed and ApplyButtonPressed methods then where I should test it? Maybe the problem is in the Presenter itself?

1

There are 1 best solutions below

0
On

I think you have a couple of options here:

  1. extract TrySaveChanges into its own class / move that logic to the model.

  2. accept that extracting common code into private methods will sometimes lead to executing those methods more than once in your tests.

To me, both would be perfectly fine.