Background
In my earlier post about Unit Test Session State in ASP.NET MVC I had demonstrated how to mock intrinsic object like Session state in ASP.NET MVC using Moq. The idea there was to abstract the access to SessionState out into separate class called SessionHelper and then use Moq to mock those method or property calls. In this post I would be using an elegant approach to achieve the same results using MVCContrib TestHelpers.Using MVCContrib TestHelpers to mock intrinsic objects
The previous approach might be helpful if we are using only one or two intrinsic object within the controller actions. Most of the times we'll be using more than one of the ASP.NET MVC intrinsic object like- HttpContext
- HttpRequest
- HttpResponse
- HttpSession
- Form
- TempData
- QueryString
These TestHelpers use RhinoMocks internally to mock the calls to ASP.NET MVC intrinsic objects.
I have modified my example from the last post to suit the changes for TestHelpers. Another advantage of using these test helpers is that we get a set of extension methods which can be used to assert results in a fluent manner. I'll demonstrate that as well in the assert section of the tests.
Without wasting too much time let me dive into the code straight away. Here are the changes to the controller.
private readonly IUserRepository _userRepository;
//private SessionHelper _sessionHelper;
public LoginController() : this (new UserRepository())
{}
public LoginController (IUserRepository userRepository)
{
_userRepository = userRepository;
//_sessionHelper = sessionHelper;
}
public ActionResult LogOn(FormCollection formCollection)
{
string userName = formCollection["UserName"];
string password = formCollection["Password"];
bool validUser = _userRepository.ValidateUser(userName, password);
if(validUser)
{
Session.Add("UserName",userName);
return RedirectToAction("Index", "Home");
}
else
{
this.ModelState.AddModelError("InvalidUser", "Invalid user name or password");
return View();
}
}
private Mock<IUserRepository> _mockUserRepository;
private TestControllerBuilder _builder;
private LoginController _loginController;
[SetUp]
public void SetUp()
{
_mockUserRepository = new Mock<IUserRepository>();
_builder = new TestControllerBuilder();
_loginController = new LoginController(_mockUserRepository.Object);
_builder.InitializeController(_loginController);
}
[Test]
public void ValidUserDetailsAreStoredinSession()
{
//Arrange
string userName = "Nilesh";
string password = "abc@123";
FormCollection formCollection = new FormCollection();
formCollection["UserName"] = userName;
formCollection["Password"] = password;
_mockUserRepository.Setup(userRepository => userRepository.ValidateUser(userName, password))
.Returns(true);
//Act
ActionResult result =_loginController.LogOn(formCollection);
//Assert
//Assert.That(result.RouteValues["controller"], Is.EqualTo("Home"));
//Assert.That(result.RouteValues["action"], Is.EqualTo("Index"));
result.AssertActionRedirect()
.ToController("Home")
.ToAction("Index");
Assert.That(_loginController.Session["UserName"], Is.EqualTo(userName));
}
Conclusion
Using TestHelpers makes it very easy to unit test the intrinsic objects of ASP.NET MVC. Additional methods to assist during asserts also makes the code more readable and easier to understand. We no longer need to abstract all the intrinsic objects. The learning curve is also very less. We can also make use of these TestHelpers to write framework agnostic Asserts. This means that we need not depend on the syntax of the unit testing framework being used to Unit Test the code. I am sure I'll come across situations in my project to demonstrate the other objects like HTTPRequest, Form, QueryString etc over next few days.Until next post happy programming :)
Note:
TestHelpers internally use RhinoMocks dll. make sure you copy that dll from which resides in the dependencies folder after MVCContrib files are extracted to the disk. Copy the RhinoMocks dll into same directory as MVCContrib.TestHelpers.dll.You can download the complete source code from dropbox - SessionStateUnitTest_WithMVCTestHelpers.zip.
Havе you evеr thought about including a little bit more than just youг articⅼes?
ReplyDeleteI mean, what you say is important and all.
However imagine if you added some great photos or video clips to give your posts more, "pop"!
Your content is excellent but wіth imɑges and cliⲣs,
thiѕ site could defіnitely be one of the best in itѕ
field. Veгy good blog!
i thoսght about this : Τimes Are Changing:
How To Password Protect Folder New Skills
Excellent weblog right here! Also your web site quite a bit up very fast!
ReplyDeleteWhat web host are you the use of? Can I am getting
your associate link for your host? I want my website loaded up
as quickly as yours lol