Dependency Injection and highly coupled objects

I consider that Dependency Injection (DI) is a very helpful pattern, I love to use it in order to reduce the coupling in my code and it helps me when writing unit tests. But sometimes the code depends on objects that are difficult or impossible to mock.

The HttpContext class of the ASP .NET MVC framework is one example of this kind of object.

I just want to check that the view is not null but the test fails. I get a NullReferenceException because the HttpContext property of the Controller is null. This happens because there is no web context when executing the test and it makes sense since the execution occurred in a test context.

The first thing that comes to mind to fix this issue is to set the HttpContext property with a mock. But I cannot do that because this property is read only and thus I am not able to set it when doing the instantiation of the controller in the test method.

And if you need to mock the HttpContext class, you cannot because it is sealed. To avoid this you can use the HttpContextBase abstract class instead but in a test environment you will have to implement it in order to mock it and you don’t want to do this. Why? Because it’s a pain to do, you will have to provide implementation for everything, it’s like creating an entire web context just for the test. And in my case I just need the user languages.

So? What now? Do we give up testing our controllers? Absolutely not, it is possible to achieve our goal without too much complications. From the beginning I tried to mock the wrong thing. What I need is the user languages not the HttpContext, so let’s remove this dependency. I created the following interface with the data my code will use:

publicinterface IWebContext
{string[] UserLanguages {get;}}

And now I will inject this interface in my Controller and I will create a specific implementation that will use the HttpContext to retrieve the languages from the request:

My test is now passing! I removed the dependency between the test and the web context objects, I can now test the logic of my controller without having to set up an awful lot of mocks.

I encapsulated my specific logic inside an abstraction that is far easier to mock. This way I was able to reduced the coupling, I was also able to increase my code coverage and all of it without losing any behavior.

You can use this technique for other properties of the HttpContext like the user agent if you want to apply some logic on it and test it. Or also for static classes/methods (that you can maybe found in your legacy code).

I hope this will help you and as usual do not hesitate to leave a comment.