UI Design Using Model-View-Presenter (Part 3)

In The Previous Episode

In the previous part of the series we finally wrote some code and implemented the three main components of the Model-View-Presenter pattern. We defined our Model class, extreme-makeover’d our old Windows Form class to a slick View-compliant class and then created a Presenter which will orchestrate all sorts of evil things so the Model and View play together nicely.

In case you missed any of our adrenaline-filled previous posts, now it is a good time to go back to Part 1 or Part 2 and drop a sweat, boy.

Wiring Everything Up

Now is time to wire up the Model, View and Presenter classes so we have a running application which does the exact same thing as our old application but with a pretty sexy code base. This wiring will take place at the Main method of the application, which will instantiate the repository class, the View and the Presenter; initialize everything and then finally run the application.

So, here is our new Program class doing what it does best:

namespace Codenough.Demos.WinFormsMVP
{
   public static class Program
   {
       [STAThread]
       public static void Main()
       {
           Application.EnableVisualStyles();
           Application.SetCompatibleTextRenderingDefault(false);

           var clientsForm = new ClientsForm();
           var clientsRepository = new ClientRepository();
           var clientsPresenter = new ClientsPresenter(clientsForm, clientsRepository);

           clientsForm.Closed += () =>
           {
               Application.Exit();
           };

           Application.Run(clientsForm);
       }
   }
}

If you smash on that Run toolbar button at this point, you will see a really nice window poppin’ up on-screen with the clients list box populated just like the old application, only that this time all data coming back and forth the View is going through the Presenter (what a controlling psycho freak). Most important of it all: You can now look in the code examples how each part has a single purpose. The Model stores data, the View displays data and the Presenter controls data flow.

Now, the only thing left to do and (hopefully) show the real benefit behind this pattern, is to try again and implement our pre-defined unit tests so we can verify our application meets all requirements.

Meeting Acceptance Criteria

Our application code has never been so ready before for some unit testing. We had some already defined, which we could not implement at the time simply because the code was being a total jack. But now, using the MVP pattern on all its glory, we are set up for it.

So, for unit testing I am using NUnit and Moq. Moq is a library that allows me to create mocks (in this case the repository class and the View interface) without having to write additional code; we don’t like to do that. Before we proceed, let’s see what a mock is and what it can do for us.

A “mock” is a fake implementation of an interface or a class which members produce data we already know– basically is like making a TV display a TiVO recording instead of an actual live show. You know, in this example we can know what the data coming from the repository class is just by looking at the code, but in the real world we might not have that source code at hand. Or even worst, that data might come from a production dabatase we don’t have access to. With a mock, we can fake a method to do or return anything we want.

Our first test is called ItShouldLoadAllClients. Since our test-naming skills are so incredibly sharp, we can imply, just by reading that title, that a clients list has to be loaded during Presenter class initialization. We first create a new method called SetUp that will run right before each time a test method runs to set everything up– in this case it will initialize mock instances for the repository class and view interface. We then proceed to create an instance of the Presenter class, which is the test subject (our lab rat, yes) and then we use the Verify method of the mock that will throw a nasty exception and make the unit test fail miserably if the specified View method (LoadClients for this particular case) was never called during Presenter initialization.

using Moq;
using NUnit.Framework;
using System.Collections.Generic;
using System.Linq;

namespace Codenough.Demos.WinFormsMVP
{
   [TestFixture]
   public class WhenClientsWindowLoads
   {
       private Mock<IClientsView> clientsViewMock;
       private Mock<ClientRepository> clientsRepositoryMock;

       [SetUp]
       public void SetUp()
       {
           this.clientsViewMock = new Mock<IClientsView>();
           this.clientsRepositoryMock = new Mock<ClientRepository>();
       }

       [Test]
       public void ItShouldLoadAllClients()
       {
           // Act
           var clientsPresenter = new ClientsPresenter(clientsViewMock.Object, clientsRepositoryMock.Object);

           // Assert
           clientsViewMock.Verify(view => view.LoadClients(It.IsAny<IList<ClientModel>>()), "Expected clients to be loaded on initialization.");
       }
   }
}

Of course, this test passes. A call to the LoadClients method is done at the Presenter constructor. The following tests are a little more complicated, since we will be setting up methods of the View and repository mocks to return what we need them to return (method setup).

Our next test is ItShouldShowFirstClientOnListDetails, which requires our presenter to load the first client on the list after initialization.

For this case, we let the SetUp method do its thing and create the respective mocks and then, at our test arrange phase, we use the Setup method to make the repository mock return a sample list of clients when the FindAll method is called. Finally, we verify the LoadClient method of the view was called; making this the assertion that makes the test case pass (and make us happy) or fail (and quit our jobs).

[Test]
public void ItShouldShowFirstClientOnListDetails()
{
   // Arrange
   var clients = new List<ClientModel>()
   {
       new ClientModel { Id = 1, Name = "Matt Dylan", Age = 28, Gender = "Male", Email = "mattd@none.com" },
       new ClientModel { Id = 2, Name = "Anna Stone", Age = 22, Gender = "Female", Email = "ann@none.com" }
   };

   clientsRepositoryMock.Setup(repository => repository.FindAll()).Returns(clients);

   // Act
   var clientsPresenter = new ClientsPresenter(clientsViewMock.Object, clientsRepositoryMock.Object);

   // Assert
   clientsViewMock.Verify(view => view.LoadClient(clients.First()), "Expected first client to be loaded on initialization.");
}

The last test is ItShouldShowClientDetailsOnListItemSelected and finding out the way it works will be your homework, dear reader. This is the most complicated of them all since now we use Moq to fire view events and wake up the Presenter, which should be listening to them.

[Test]
public void ItShouldShowClientDetailsOnListItemSelected()
{
   // Arrange
   var clients = new List<ClientModel>()
   {
       new ClientModel { Id = 1, Name = "Matt Dylan", Age = 28, Gender = "Male", Email = "mattd@none.com" },
       new ClientModel { Id = 2, Name = "Anna Stone", Age = 22, Gender = "Female", Email = "ann@none.com" }
   };

   clientsRepositoryMock.Setup(repository => repository.FindAll()).Returns(clients);
   clientsRepositoryMock.Setup(repository => repository.GetById(1)).Returns(clients.First());

   clientsViewMock.SetupGet(view => view.SelectedClient).Returns(clients.First());

   var clientsPresenter = new ClientsPresenter(clientsViewMock.Object, clientsRepositoryMock.Object);

   // Act
   clientsViewMock.Raise(view => view.ClientSelected += null);

   // Assert
   clientsViewMock.Verify(view => view.LoadClient(clients.First()), "Expected first client to be loaded on initialization.");
}

Conclusion

Making code testable is not easy at all. No, really, AT ALL. At least not at first, since you have to think on all the possible test scenarios your code could go through. But in the long term, this is what makes testable code more robust and clean than regular hastily thrown together code.

Okay, this makes it up for it. Hope you enjoyed it and learned a couple things. Stay tuned for more talk on patterns and good practices and maybe really off-topic things.

Oh! Don’t forget to check out the code examples (including an exciting port on Java).

Code Examples

One thought on “UI Design Using Model-View-Presenter (Part 3)

  1. Pingback: UI Design Using Model-View-Presenter (Part 2) | Informatech CR Blog

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s