Creating Unit Testable Applications in ASP.NET MVC – A Beginner’s Tutorial

In this article we will talk about creating unit testable applications using ASP.NET MVC. We will also talk a little about test driven development and see how we can design and develop ASP.NET MVC application in such a way that they are easily testable.

Background

Test Driven Development(TDD) is gaining momentum with each passing day. The reason for this is that with TDD we can not only built robust applications but also have a proof that the application is working correctly from a functional perspective by having successfully unit test cases on our modules. Also, the projects following agile/scrum methodology find TDD very useful because the major challenge in scrum is to define when our “done” is done. If we follow TDD approach then we know that when all our test cases are passed, we are done.

ASP.NET MVC application provide a very good support for TDD because we can write unit test directly against our controllers without needing any web server. Doing so we can be sure that the controllers are working correctly from a functionality perspective.

In the rest of the article we will discuss how to design and develop MVC applications that are easily testable from unit testing perspective.

Using the code

The first thing that we need to understand is that the Controllerclass can be instantiated like normal classes. This is unlike the WebForms application where the pages can only be invoked by web server. This possibility of being able to instantiate the Controller classes open the door for writing test cases that will directly test the controllers logic without needing any web server.

We will now create a simple MVC application that will perform CRUD operations on a table. We will design this application in such a way that the Controller are fully testable with dummy data without even touching the actual database.

Database

Let us create a very simple database containing one table as follows. We will perform CRUD operations on this table from our MVC application.

Db

Data Access

For data access we will use entity framework. The benefit of using entity framework is that it will generate all the data access logic for us and will also generate entities for the respective tables that we can use as Modelsin our application. The generated entities for our sample database will look like.

entity

Repository and Unit of Work

Now we have the ObjectContextand entities ready with us. We can very well use the ObjectContextclass directly in our controller to perform database operations.

But if we do this our controller is not testable. The reason is that when we instantiate the controller class and call the index function, the Contextclass will be created and it will hit the actual database.

Now how can we solve this problem. This problem can be solved by implementing Repository and Unit of Work pattern. If we have only one Repository class containing the ObjectContextthen we don’t need Unit of Work but if we have multiple repository classes then we will need unit of work class too.

Note: It is highly recommended to read the following article before reading this. Understanding Repository and Unit Of Work pattern is essential to create testable MVC applications. Please read this details: Understanding and Implementing Repository and Unit of Work Pattern in ASP.NET MVC Application[^]

Let us create a simple interface defining the contract for accessing the books data. we will then implement this interface in our repository class class. the benefit of doing this is that we can then have another class implementing the same interface but playing around with the dummy data. Now as long as the controller is using the Interface our test projects can pass the dummy data class. We will create and pass the dummy class to the controller from our test project.

And the concrete repository class that performs the actual database operations will look like:

Now the Responsibility of the UnitOfworkclass will be to create the ObjectContextand Repositoryclass and pass them to the controller.

Our controller can then use this UnitofWorkclass to perform the database operations as:

So from the design of our application looks something like:

designReal

Let us try to run the application so see that it is working.

screenshot

Dependency Injection – Understanding how things work

Before moving ahead let us see what is happening in the controller in details.

  1. The UrlRoutingModulewill parse the URL and call the controller.
  2. The default constructor of the Controller class will be invoked.
  3. This constructor will create a UnitOfWorkclass by using its default constructor.
  4. In the UnitOfWork'sdefault constructor the BooksRepositoryclass will be instantiated.
  5. The UnitOfWork class will point to the real BooksRepositoryimplementation.
  6. All the actions of the Controller will use the real BooksRepositoryclass to perform actual CRUD operations.

What we have done in our controller is that our controller is using UnitOfWorkclass. The UnitOfWorkclass contains a handle to the interface. So we can make this to use either the BooksRepositoryclass or any other class that is implementing the same interface. The We are doing Dependency injection using the UnitOfWorkclass’ constructor.

Now if we need to test the application without touching the database what we can do is that we can create a dummy class that is also implementing the IBooksRepositoryand use this dummy class with our UnitOfWork. Which will effectively let our controller work with the dummy class.

Creating the TestProject

Now from our test project we need to perform following activities.

  1. Create a dummy class DummyBooksRepositorywhich will implement IBooksRepository
  2. Create the Test functions for all the functions of our controller.
  3. Instantiate our dummy repository i.e. DummyBooksRepository.
  4. Create the Unitofworkby calling the constructor accepting a parameter of type IBooksRepository. We will pass our dummy repository i.e. DummyBooksRepositoryin this constructor.
  5. The UnitOfWorkclass will now point to the DummyBooksRepositoryimplementation.
  6. Create the Controller by calling the constructor that accepts UnitOfWorkby passing the object that we created in previous step. This will effectively make the controller to use the DummyBooksRepository.

Let us not try to follow the above steps and try to create our unit test project. First of all let us create the dummy repository class implementing the IBooksRepositoryinterface.

The resulting design will look like:

designComplete

Now from our test class we will instantiate this dummy repository class and create a unit of work that will use this class. We will then instantiate the Controller that we need to test by passing this UnitOfWorkclass object into that.

Now the next step would be to write the unit tests for all the actions of the controller class. Now since the controller is using the dummy repository, from the functionality perspective the controller class will behave the same but will operate on our dummy repository class rather than actual repository class.

To test the Retrieval Methods of the controller let is add the following functions to the class.

Now lets add the functions to test the create, update and delete functions.

Now let us run our unit tests and see the result.

testResults

Note: The above mentioned code snippets only show the valid operations. We should also incorporate test cases that perform invalid operations. Try to introduce some problem in the controller class and see how the tests will fail.

Point of interest

In this article we saw how we can utilize the power of repository and Unit of Work pattern to create unit testable ASP.NET MVC applications. We also saw how testing MVC application don’t require any web server and they can simply be tested by instantiating the Controller classes from the test project. This article has been written from beginner’e perspective. I hope this has been informative.

Download sample code for this article: TddMvcSampleApp

One thought on “Creating Unit Testable Applications in ASP.NET MVC – A Beginner’s Tutorial