MVP in Action - Unit Test
This is in continuation to the article geekswithblogs.net/rajeshpillai/archive/2009/11/29/mvp1.aspx. This post will deal with
writing simple unit test case for the "User" user creation use case we covered in the above blog post. For some quick benefits of unit test
please refer my earlier post geekswithblogs.net/rajeshpillai/archive/2009/11/28/some-notes-from-my-tdd-session.aspx
Background
Unit testing means testing a piece of code or a method. White unit testing we need to stub or fake out external dependencies
so that the test can run in isolation. The following two test cases we will cover
- When saving a user with valid data should display "Successfully submitted the user." message on the view.
- When saving a user with empty name should display "<ul><li>user:User name cannot be empty</li></ul>" the
following message on the view.
Let's proceed with writing the test cases. We will be using the "Rhino Mock" mocking framework to mock our views. Rhono mock is availabe at ayende.com/
1. Test Case 1 :

The name of the method should indicate the "action" and the "expected result". Let's dig line by line to understand the test case. I have used MSTest. You
can use your preferred unit testing framework. Basically we are following the "AAA" paradigm. It stands for "Arrange->Act->Assert". This is just a convention
but would be quite handy to follow.
The first thing we do is "Arrange" our objects. We mock the IUserView using RhinoMocks GenerateMock() method.
Mocking allows you to set expectations on the object. We need to also stub the view in this case so that the appropriate "User" object can be created.
Line 72 to 75 sets the stubbed value on the view. Then we set the expectation on the "Message" property on the view. Next
comes the "act" part. We do this by invoking the method on the presenter which we intend to test. And the assert is done
by calling the "VerifyAllExpectations" method on the view. When you mock a view using RhinoMock additional extension
methods are available on the mocked object. "VerifyAllExpectations" is one of them. If our expecation is correctly verified
the test passes. Let's see the result in action.

You can see the the test passes. Let's get on to the second test case.
2. Test Case 2 :

Let's execute the test and see the result.

We pass the name as "empty string" and the test works as expected. You can experiment with the test. The simplicity of this test shouldn' dicourage you. They may be a life saver where you have many integration points where different
teams are working on different modules and you want to ensure that your code is working as expected. If any other
piece of code changes it should be easy to detect rather than going through the entire sanity test again.
Here is the presenter code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Web.ViewContracts;
using Demo.Service;
using Demo.Service.Messages;
using Demo.Objects.Entity;
using System.Text;
/// <summary>
/// Summary description for UserPresenter
/// </summary>
///
namespace Web.Presenter
{
public class UserPresenter
{
IUserView view;
IUserService userService;
public UserPresenter(IView userView)
{
view = userView as IUserView;
userService = new UserService();
}
public void Save()
{
User user = new User();
user.Email = view.Email;
user.IsActive = view.IsActive;
user.Password = view.Password;
user.UserName = view.UserName;
UserResponse userResponse = userService.Save(user);
if (userResponse.Status == ServiceStatus.Success)
{
view.Message = userResponse.Message;
}
else
{
StringBuilder sb = new StringBuilder(100);
sb.Append("<ul>");
foreach (ErrorInfo error in userResponse.Errors)
{
sb.Append("<li>" + error.key + ":" + error.message + "</li>");
}
sb.Append("</ul>");
view.Message = sb.ToString();
}
}
}
}
The presenter code is kept simple for demonstration purpose.
Hope you enjoyed this post. As best practice you can move out the "hardcoded" values from the test into some constants or config. Watch out for this series as I will post examples of more complex scenarios and its real life implications.
Happing Testing !!!