Model View Presenter - is testing the presenter enough?

Posted Monday, November 28, 2005 11:00 AM by Dan Bunea

Source code: Download


Lately, I have noticed that the Humble Dialog Box or Model View Presenter are gaining more and more acceptance among software developers, especially in agile communities, because of its benefits regarding the very good separation between the view and the behavior and because it can be very easily unit tested, on a problematic field: user interface.

Let's meet Model View Presenter

In model view presenter just as Martin Fowler or Michael Feathers [2] say, the logic of the UI is separated into a class called presenter, that handles all the input from the user and that tells the "dumb" view what and when to display. The special testability of the pattern comes from the fact that the entire view can be replaced with a mock object and in this way the presenter, which is the most important part, can be easily unit tested in isolation. Let's take a small sample:

A client writes in a user story:

User management

The system will support managing users. Each user can have a username and a password. The system will present a list of user and when one is selected, it can be edited. Also there will be functionality to add new users and to be able to select a user from the list and delete it.


Ok, now let's get to work:

Our view should need the following data, which will be put into an interface:



The UsersList represents the list of users, and the User is the current user selected at a certain time.

When the UI is displayed, we want to be able to see the list of available users, and by default the first in the list to be selected. Let’s write a small test for that. Having no view, we will make a simple implementation of the IUsersView, called UsersMockView. Using it we will be able to see if the presenter when it is initialized sets the needed list and the first is selected in it.



where we have:



And for the data we use a separate model class, like:



If I want to make my test compile, I must write my presenter, see the test failing then keep working on it until the test is working:



and now it is time for a new test, and a small refactoring in the test code:




Now we can go further and add the missing code ... until it works. We then follow the same procedure until we have quite a suite that test selecting a user in the list, updating its details, deleting a user, deleting all the users, and others. Now we know we have a Presenter that works fine. At least where it is tested.



Could we have used a dynamic mock?



I like writing in some cases the mock objects by hand. However there are a few dynamic solutions that can prove quite helpful, like NMock [3] for instance. NMock can create mock objects, using Reflection.Emit and your interfaces “on the fly”. Then it is also very useful when it comes to seeing what methods were invoked in the mock object by your class under test. You can also set predefined responses, when the class under test invokes your mock object, but that is another matter. Let’s make a small sample, just as we did before manually. For the TestInit, using NMock it will be like:






It works. The presenter has invoked the properties of the mock object, once as expected and set the expected values. This way we can throw away our previous tests, and can build a new presenter based on testing with dynamic mock objects.

Implementing the real view

If you read Michael Feather’s “Humble Dialog Box” article, you’ll be able to see very well how the real view should be built. The presenter sets the values into the view which are the propagated to the properties of the controls, much like:



but once .NET was released, it comes with the concept of data binding, and there are some developers that do not want to ignore it and use the “old and safe” ways as above.

How does MVP cope with data-binding?

.NET 2.0 comes with a new and much better concept for data binding then 1.0 or 1.1 did, the BindingSource. This now has the possibility to be connected to different kinds of data sources, including business objects. For our interface we create two: bsUser for User and bsUserList for the list of Users. Then for binding we can use, the designer as:




Now, we go back to our properties that are used by the presenter to “push” data into the view to be displays, and modify the code to use the binding sources as follows:



As you can also see, user actions on the view are delegated to the presenter, which is now fully in control of what behavior of out user management interface.

If we run the tests again, they are all green, all succeed. This is great, but this green is false if you think that it works with data-binding because the tests do not touch in any way the actual view. So what do we do?

A first option would be to leave it like that. But since a view for a desktop application is not exactly as “dumb” as we would like, and can quickly become a source of error, we need to add some tests.

Using a functional testing framework like NUnitForms or SharpRobo could be a solution but this can result in tests that test the same thing, and that is not exactly maintenance friendly. But wait, what if our stub is not exactly a stub but an extension of the view itself, to which we can add testing code. For this we inherit, the real view and create ExtendedUsersView. Now we want to modify the testing code in such a way, that the existing code is still reused. For this we inherit the manual test we have written, and just override the SetUp method:



If we run it, it will run the initial tests but on the actual view. It needs to be shown as data-binding to the controls is done when the controls become visible, but that is not a problem. The problem can be speed, but if you run the code you’ll be able to see that the difference is not that significant. If speed is a problem, then maybe you can run the tests that use the actual view, more rarely, as you can get quite enough feedback from the mock tests.

The process

About the process of building destop application pieces, the way I have constructed the application above, might seem wrong, as using TDD, I built the presenter, but I did not have the view yet, and that was constructed later on the exact same set of tests. In practice I wouldn't recommend this, as the first step, building the presenter without the view, using TDD might lead to a code that will need big refactorings (both presenter and tests) when the view is built. A better approach would be to construct, a two test cases, one inheriting teh other, with two setup methods, one with the mock view, and one with the actual extended view, then build a test inside the first, and build some code on it in both the presenter and the view, then add a new test and so on, until we have tested both the presenter and the view, having both tests that are fast and isolate the presenter's bahavoius and tests that also cover the view.

Conclusion

I have tried to present a solution, that can cover more of the code with unit tests, then only the presenter, as for desktop applications this can be an important issue. I have also tried to find a solution that works with data-binding, and what I have found seems ok so far, but only time and more research and tests can really tell if this was a good choise….

1. Martin Fowler - Model View Presenter
2. Michel Feathers - The humble dialog box
3. Peter Provost - TDD in .NET
4. Jeremy Miller - A simple example of "humble dialog box"
5. Ben Reichelt - Learning teh model view presenter pattern

Comments

# re: Model View Presenter - is testing the presenter enough?

Monday, November 28, 2005 12:44 AM by Waseem Sadiq

Hi Dan,

Your images seem to be broken. Interestng article though.

# re: Model View Presenter - is testing the presenter enough?

Monday, November 28, 2005 2:11 AM by Dennis van der Stelt

Great article in explaining the MVP pattern, including some great examples, even with databinding!

I'm doing a presentation on TDD this evening at my company. To explain dependency injection, I used the MVP in slides. But it was too much code to handle, as experienced in a test run. So I removed the example and just show a one class implementation. Now I can refer to your article when talking about DI. Thanks! :)

# re: Model View Presenter - is testing the presenter enough?

Monday, November 28, 2005 5:14 AM by Dan Bunea

Hi,

Sorry for the big images. I had some problems when posting code, it was reformatted and I came with the idea of putting images. However this layout is not very friendly with my wide images. I will fix it somehow.

For dependency injection and inversion of control, I really suggest you to take a look at Castle's Widsor (www.castleproject.org).

Thanks,
Dan

# re: Model View Presenter - is testing the presenter enough?

Tuesday, November 29, 2005 2:42 AM by Marc Jacobi

Good Stuff. Thank you. You've answered a question I always had in your example.
I always wondered what the use of defining an interface for the view was.

I gathered that a fundementally different view would also require a different controller / presenter. Why define an interface if these are paired anyway. The ability to use a mockup view for unit testing is a valid reason. Do you know of any real-life examples why one would want to define a view interface (other than unit testing)?

# re: Model View Presenter - is testing the presenter enough?

Wednesday, November 30, 2005 2:42 PM by Dan Bunea

Hi,

For me testing is extremely important, so if the IView interface helps with that, that is good enough for me. Having you application covered with automated tests has great benefits and makes the application "stay alive" for a much longer time.

However, I belive that MVP can really encourage, using multiple views for a presenter, if needed. If you can switch the main view with a mock view, then you can switch it with other views as well.

I remember, that for a year or so we used a third party grid for one of our application. Now we want to move from that grid to another. We are taking it step by step, but since the logic and data are completely separated from the view, that makes the change easier. So we remove the old grid, and put the new one. Run the test, if it fails, we continue until it is running. Where we have used MVP and have tests, the move is done in minutes and hours, and we are prettly much confident, that the functionality is the same. Where it wasn't used it is much slower, as manual tests take lots of time,and if something is wrong they need to be run again and again.

I am also starting a new application now. We want this application on the market for at least 3 years. So we need to figure our a way to build it with Windows.Forms then maybe be able to move to XAML. What better way then MVP?

Thanks you,
Dan

# re: Model View Presenter - is testing the presenter enough?

Monday, December 05, 2005 5:23 AM by Josh Chisholm

Hi Dan,

Nice article, but I would like to see your code! Please fix the images and/or zip.

Thanks,

Josh

Leave a Comment

(required) 
(required) 
(optional)
(required)