Cricket.Net: Part 3 – Unit Testing

Summary
Cricket.Net is a new open source project that I’ve started on Codeplex. It will be a web application that will be used for tracking software bugs. Cricket.Net will be written in C# using HTML5, ASP.NET MVC 3, Entity Framework 4.1 Code First, StructureMap, and the Onion Architecture. This project will be an example application to demonstrate how to use these technologies together to build a web application from the ground up.

I’ll also be going through using Mercurial both on my system and pushing changes to the Codeplex site.

Cricket.Net Series:

Unit Testing Thoughts
The idea behind unit testing is to write a very simple piece of code to test your business logic for one condition.  The test either passes or fails.  As you build your application, you may have hundreds or thousands of these tests.  By keeping them very simple, and not running any time intensive operations such as I/O, these tests will be able to execute very quickly and give you an indication that your program is working correctly.

Unit Tests become most useful when your application has been completed for a number of months and then a required change is needed.  As you modify your code, you can re-run your unit tests to make sure your new modifications have not broken your program in some other area.

The difficult part of unit testing is thinking of all the different angles to test your piece of code.

As you write your tests and develop your application, you will undoubtedly break some of the tests that you had previously written.  These will then need to be revised.  This is the process you will go through to fully flesh out your application and develop it from a user (of the code) perspective.

I usually begin by writing all my tests against the Controllers since that is the entry point to the things my application will do.  I also try to write tests against the requirements of the application only.  If you test all of an application’s requirements, then you are making sure the application is doing what your customer wants it to do.  There is no need to test 100% of the code you write.  As mentioned above, you will break unit tests as you develop your application and continually have to revise them.  Revising tests that cover 100% of your code could be very time-consuming.

Unit Test Controller Shell
Since we’ll be testing Requirements, the first thing I do is create a new folder in the Unit Test project called Requirements.  There is currently a Controllers folder that we will remove later on.

Next, create a new Class item called ApplicationControllerRequirements.

The new class will need to be modified for unit testing. Below is the basic shell for a unit testing class.

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Cricket.UnitTests.Requirements
{
  [TestClass]
  public class ApplicationControllerRequirements
  {
    [TestInitialize]
    public void Setup()
    {
      //This method runs before each test method.
    }

    #region Test Group

    [TestMethod]
    public void unit_test_method()
    {
      //Arrange.

      //Act.

      //Assert.
    }

    #endregion
  }
}

There are three attributes being used on this class: TestClass, TestInitialize, and TestMethod.

  • TestClass – Signals this is a unit testing class.
  • TestInitialize – This is an initialization method that is executed before each test method.
  • TestMethod – This is a unit test function.

A unit test only tests one condition and there may be many conditions we need to test for, so I like to group my tests together using regions. These can be collapsed out of the way within Visual Studio to make it easier to work on other unit tests without the unwanted ones getting in the way.

Within a test method, there are three things that need to be done:

  • Arrange – This consists of any mocking or setup tasks.
  • Act – This is the execution of the action you are testing.
  • Assert – This is the verification you received the desired result.

Writing The First Unit Test
First we will start with a very simple test against the Index action of the controller. This is the default action that is called if none is specified in the application’s URL.

We’re going to test if the Index controller returns a ViewResult. Notice the compiler now has an error on the “controller” object. This is because we haven’t created it yet. One nice aspect of TDD (Test Driven Development) is you think about how the interface to your code is used, and then develop the code afterwards.  Now we know we need to create a “controller” object and it needs to have a method called “Index”.

Since the initialization of the controller will need to be done for nearly all tests in this class, we’ll add that to the Setup() method.

Now the compiler is showing errors on the “ApplicationController” class.  We need to create the new controller in the main project.

  • Right-click on the Controllers folder in the main project.
  • Select Add, then Controller.
  • Type in the Controller Name: ApplicationController and click Add. (Leaving the Template set on Empty Controller)
  • In your unit test class, add the using statement: using Cricket.Controllers;
  • Under the Unit Test method, add a cast to the “Act” line: ViewResult result = (ViewResult)controller.Index();
  • Also, don’t forget to change the name of your unit test method to something meaningful. The more description you can put in this method name, the better.

Running Your Test
Ideally, you want to see your test fail first, to make sure you didn’t accidentally write a test that can never fail.

We can quickly test this by adding the following line to our Index method on the ApplicationController:

return RedirectToAction("Index");

A ViewResult is expected in the test, so now it will fail.

After you have verified the test has failed, change the Index method back to the following:

        public ActionResult Index()
        {
            return View();
        }

Now, your test should pass.

Another Test
Next, we’ll add another very simple test to verify the correct view is being returned from the Index method.

        [TestMethod]
        public void index_action_should_return_the_index_view()
        {
            //Arrange.

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

            //Assert.
            Assert.AreEqual("Index", result.ViewName, "result.ViewName");
        }

Running this test will fail because the Index method is not returning a specific view. To change this, modify the Index method to show:

        public ActionResult Index()
        {
            return View("Index");
        }

Now the test will pass because we are specifying a view to display.

Final Thoughts
Unit Testing does take some time to get the hang of it. It is well worth it in the long run to know you can modify your program to add new features without breaking the current functionality.

As we develop this application, these tests will become more complex, but by focusing on one result and writing multiple tests for each action, we can work through it.

The empty “Arrange” comment for each of these tests is a place holder for mocking objects we may need to place there in the future. Typically, Unit Testing developers say to place all setup code in the arrange.  I like to place common setup tasks that will happen for each test in the “Setup” method where I only have to code them once.  If there is a specific setup task needed for a single test, then I will place that under the “Arrange” comment.

Visit the project site at: http://cricket.codeplex.com.
Download the source code from this post at:
http://cricket.codeplex.com/SourceControl/changeset/changes/df77b3e9d546

You may also like...

2 Responses

  1. Frank vd Geld says:

    Question,

    I can’t seem to figure out how you can use the entityframework & codefirst into the Onion Architecture “Pattern” without breaking the whole concept?

    Did you ever finished creating the demo project on codeplex?

    With kind regards,

    Frank van der Geld

  2. No, I haven’t finished the demo yet. Using onion architecture, the key is to keep the oa stuff inside the infrastructure project and pass single domain objects or collections of domain objects from the repositories to the service classes. Repositories are in infrastructure project while service classes are in core project. By doing this, the Ef model is separate from the domain model making it possible to replace Ef with something else without having to worry about messing up the business logic in the core project.. You’ll also need to handle mapping Ef model objects to domain model objects.

Leave a Reply

Your email address will not be published. Required fields are marked *