-->

21/01/2012

Unit Test Case writing for a MVC Project

In this post we will learn how to write Unit Test Cases for a MVC project.
One strong reason behind choosing MVC approach is TDD (Test Driven Development).

If we say my Data layer / Business Layer is 100% tested,it should pass all the positive scenarios and fail in all negative scenarios.
In order to do that, we need to write test cases for all the public methods present in different layers of our application and test them thoroughly.

I have created a very simple POC for demonstrating on how to write test cases.


Step 1: Create a MVC Web application. While doing so, Visual studio will prompt set of inputs regarding the Template, View Engine and the third one is about Test Project.
Now, Select the option to create a Unite test project to test your MVC project.

Step 2: By default your application will be created with a HomeController with two action methods.
public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";

            return View();
        }

        public ActionResult About()
        {
            return View();
        }
    }
Step 3: Now, open test project, it also contain a HomeControllerTest.cs file, and you can see two test methods written for both of the Controller methods we have.
[TestClass]
    public class HomeControllerTest
    {
        [TestMethod]
        public void Index()
        {
            // Arrange
            HomeController controller = new HomeController();

            // Act
            ViewResult result = controller.Index() as ViewResult;

            // Assert
            Assert.AreEqual("Welcome to ASP.NET MVC!", result.ViewBag.Message);
        }

        [TestMethod]
        public void About()
        {
            // Arrange
            HomeController controller = new HomeController();

            // Act
            ViewResult result = controller.About() as ViewResult;

            // Assert
            Assert.IsNotNull(result);
        }
     }
Observe that class has [TestClass] and all test method have [TestMethod].
This makes the frame work to understand that these methods need to b executed while running a test Project.

For every test method there will be typically three steps.
1. Arrange - All the values will be assigned to variables to test the desired functionality.
2. Act - Execute and capture result of the Method using the Parameters we created in earlier step.
3. Assert - Compare the actual result with the Expected one.

Step 4: Lest test the existing functionality. Make test project as startup project and hit F5.

See the Test results Pane for output of testing.

Step 5: Lets Add a Controller Method and test it using test case project.
Method Added:
public ActionResult TestControllerMethod(int i)
 {
     if (i > 200)
         throw (new Exception("Out of range"));
     return View();
 }
Test MethodS Added:
[TestMethod]
        public void TestControlMethodWithValidInput()
        {
            // Arrange
            int i = 150;
            HomeController controller = new HomeController();

            // Act
            ViewResult result = controller.TestControllerMethod(i) as ViewResult;

            // Assert
            Assert.IsNotNull(result);
        }

        [TestMethod]
        public void TestControlMethodWithInvalidInput()
        {
            // Arrange
            int i = 250;
            HomeController controller = new HomeController();

            // Act
            ViewResult result = controller.TestControllerMethod(i) as ViewResult;

            // Assert
            Assert.IsNotNull(result);
        }
Observe that the method execution should fail when the input parameter value is more than 200, and we are passing 250 in Test Method.
Output:

Step 6: Now lets look at how to test other layers of the application. How it is different from what we have done until now?




Let me answer you. Its nothing different. We can follow the similar approach of writing test methods using the 3 steps defined above. Just to isolate the layer wise test cases, try to maintain a Test file for each and every class file. This means , if you have a Serivice.cs file in our application, try replicating the same folder structure in test project as well and keep the test class name as "ServiceTest.cs".

Its not mandatory to replicate folder structure or the file name appended with Test, but its a Best practice. The actual logic lies in the Class you initiate and Method you execute.

With this we have learned the basics of Testcase writing in MVC using Visual Studio Test Framework.

Is it helpful for you? Kindly let me know your comments / Questions.



4 comments:

  1. no no no no!!!

    you should never have failing tests!!!

    Add the expected exception attribute

    [ExpectedException(typeof(ArgumentOutOfRangeException))]

    to TestControlMethodWithInvalidInput

    run your test again.... still fails....

    change the method to throw ArgumentOutOfRangeException

    instead of a general exception

    and voila!!!

    test succeeds!!!

    Again. . tests should ALWAYS succeed!!!!

    ReplyDelete
  2. Hi
    I failed the test case just to demonstrate how it looks like as we are looking into the basics.... Will do all advanced handling things in upcoming posts. Thanks for your suggestion, will do it.

    ReplyDelete
    Replies
    1. Hi,

      Can you post a POC advanced handling of exceptions? The POC posted with basics is really good and gives a good headstart.

      Thanks

      Delete
  3. Hi Prathap, Its a great blog which explains testing MVC with easy step. Thanks

    ReplyDelete