We’ve been building out the site CurbstoneComment.com using MVC 4 and Code First Entity Framework 6 and it’s been delightful taking advantage of all the magic offered up via these whiz bang technologies that do so much useful work under the hood. As the site starts coming together, we don’t want to wait too long before starting to write some unit tests, since we’re such big believers in Test Driven Development (TDD). It is comforting to know that MVC promises to enable testability without requiring dependencies on a Web server, a database, or external classes.
In previous posts, we’ve set up the MVC project, deployed it on our web server (yes, it’s far from production-ready but we don’t have DEV and QA environments set up for these purposes), we’ve used EF to create our database model and provision our database, and we’ve used MVC Scaffolding to build our controller and repository classes. There have been several re-do’s and we’ve discovered that some EF functionality didn’t appear to work as advertised (but we worked around it), but overall this project has gone very smoothly with every little coding needed on our part.
Take a closer look at the ItemRepository class that MVC Scaffolding created. The main problem we’re going to face in creating unit tests for this code is separating the context object (of type CCContext) from the data layer. The context object opens and maintains the connection to the database, but we don’t want our unit tests to be dependent on any database.
The problem is that our unit test component is going to be dependent on the database connection in another component. A way to solve this problem is to ensure that we build a loosely-coupled set of software components so that high-level modules don’t depend on low-level modules. This can create headaches (DLL hell!) as our application gets more and more complicated.
Two design patterns can help with this:
- The Dependency Inversion Principle provides guidelines to write loosely coupled classes.
- The Inversion of Control is a mechanism with which we can make higher level modules depend only on abstractions, rather than concrete classes.
Together, these patterns are rolled into a big, popular design pattern called Dependency Injection. For a full discussion of DI, check out this article.
If you noted that our ItemRepository class implements an interface IItemRepository, you will begin to see how we are going to approach this.
In our Unit Test project, we will create an in-memory ItemRepository that also implements IItemRepository. We will write code that mocks the DBContext and also mocks the magic of MVC by creating a class that mocks the HttpContext. We will be invoking the MVC routing engine without using a web server!
We want to test the controller’s ability to select an Item from a list by the correct ItemId.
We create our test data, the repository manages it as if it were a live database, and the controller looks up the correct item and our test passes.
TDD is a widely accepted best practice these days in the software industry. Unit Tests have their limits and we will need to write Integration Tests as we get our application more complete and connect it with a database. Write those unit tests first and you will smile more later!