To Test Or Not To Test

Overview

I’ve never worked for a company that has required unit tests to be maintained for a project. The places that I’ve worked have certainly encouraged me to test my code. However, I don’t know if they have really bought into the idea that you should spend the time to establish unit tests up front and maintain them as you make changes to the project. Perhaps at least partially as a result of this, my personal projects also do not have well maintained unit tests.

When you create a new ASP.NET MVC project in Visual Studio, you are prompted regarding whether or not you would like to create a test project. This is a great encourager to get folks started down the road of planning out unit tests from the beginning. Unfortunately, I have ignored that prompt each and every time that I started out a new MVC project. However, this week, I thought that I would take a look at what it would take to add unit tests to one of my existing projects. I figured what better way to do this than to add them to the MovieApp project that I talked about in a previous article.

Adding Tests

Adding tests to an existing MVC project is quite easy. All that you need to do is to right-click on existing controller method (for example) and select “Create Unit Tests”. When you do this, Visual Studio will prompt you for some additional parameters.

You can select what project your test will be added to. It can be an existing project, or Visual Studio can create an entirely new test project for you. This is great when you are wanting to add tests to an old project. Visual Studio does a lot of the grunt work needed to get you started. In fact, if you go with the defaults and click OK for the first test that you try to create, Visual Studio will create a new testing project for you that includes a new class corresponding to your controller and a new method corresponding to the controller method that you asked to create the test for.

Once you start adding tests, you will probably want to configure Visual Studio to run them every time that you build. Fortunately this is easy as well. All that you have to do is click on the Test menu, select Test Settings, and finally select Run Tests After Build. This helps you to get immediate feedback regarding how code updates impact your existing tests.

Although automatically running unit tests is easy, I would like to see a failed test result be more obvious. From what I can see, it looks like you need to open up Test Explorer to see that result. I would prefer for Visual Studio to prompt you with a notification for a failed test and/or stop you from debugging until you fix the test. At least I would like for this behavior to be an option. I can understand how it would be annoying for some users.

Mocking Up Objects

A given controller method will likely need access a number of different objects. You may not want to instantiate a full version of this object within your test method. If not, you will be using what is know as a mock. For example, take a look at the following controller method, which returns a list of movies.

This method is quite simple, but it does require the use of a movies database repository (the _repo variable). If we are focused on testing the controller method itself, we will want to leave the database out of the picture. We don’t want our test method to fail just because the database is inaccessible. As a result, we would want to mock up our database repository.

There are a number of mocking frameworks available for .NET, but one of the most popular is Moq. I have worked with this one a bit in the past, so I decided to give it a shot once again. To include Moq in your project, you will want to add the latest Moq NuGet package to your test project.

Example Test

While researching this article, I ran across DanylkoWeb’s Ultimate Guide to Unit Testing in ASP.NET MVC. I found it to be quite informative, and it served as an inspiration for the example unit test that I am providing here. If you would like to see a more thorough coverage of MVC unit testing, that is a great place to start.

Below is my example unit test for the previously discussed Index controller method. In this example, I am mocking up my movies database repository. Here I provide some example data, and then setup a placeholder GetAll method that will be called from my Index controller method. The Mock<IMoviesRepository> object that I create is done using the Moq mocking framework.

At the tail end of the test method, we perform two assertions that determine whether or not the test fails. First, we check that the result is not null. We should have received a result from the Index method. Next, we confirm that three movies are available in our list of movies, which correspond with the three movies at the top of our code example. If either of these assertions fail, the test will fail.

Example Project

At the end of this article, I will provide an updated version of the MovieApp solution that includes a test project. In there, you will find tests for each of the methods in the Home controller. Some of these tests are quite simplistic. Obviously, the whole web application is quite simplistic, so this probably makes sense.

One way that the tests could be further extended would be to add checking for invalid movies in the tests for the Create and Edit methods. To do this, we might want to create a movie view model that uses data annotations to put restrictions on the movie properties, such as being a required field or allowing a certain maximum number of characters. After doing this, we could test for each of the restrictions that we have put into place.

Conclusion

While researching this article, I found the best sales pitch I have ever heard for why you should invest time in maintaining a standard set of unit tests. In a recent post, K. Scott Allen said that unit testing taught him everything that he knows. He argues that unit testing will force you to learn such tough topics as how to properly apply design patterns and decompose classes. The reasoning is that a poorly architected class will be much more difficult to test. His argument has encouraged me to spend more time on unit tests, as I believe that I have a lot to gain by putting them to use. Thankfully, Visual Studio makes it easy to get started, and I hope that this article will help you as you start down the road to unit testing success.

Leave a Reply