With the MVC pattern, controllers play a vital role in producing the behaviour that is expected when the website is running.
When it comes to unit testing, being able to isolate parts of the code from separate areas of the application can be necessary, particularly if the real version of the implementation itself is too awkward to test - a common issue with controllers.
Mocking Things Out
Fortunately, we can create a “mock” version of an implementation which is able to act like the real thing, specifically for testing purposes.
Like everything in the tech industry, there are always multiple choices on offer…
Pronounced “mock”, and to quote -
“Moq is the most popular and friendly mocking framework for .Net”
Moq is designed to allow you the developer to manipulate your units of code and separate out cumbersome dependencies for clear isolated testing…and it supports .Net Core!
A Typical Scenario
In a typical ASP.Net MVC Core implementation, a controller will have a dependency which has been injected at constructor level, and is being utilized within an action to return a view model of data to the relevant view.
Our Dependency Code
Firstly, let’s put together a basic service class with an interface -
Our Controller & Action Code
Next, we can inject our service into the controllers constructor, define our Index action and return the data to the view -
Mocking & Testing Our Controller Action Unit
Based on the aforementioned scenario, our steps for mocking & testing a specific controllers action method would be -
Create a mock version of our dependency.
Call the Setup method to explicitly state how the dependency should behave when it’s called.
Inject our mock dependency into our controller.
Act out the action method.
Assert that our results are valid.
Our HomeController Index action is designed to return all of the user accounts from our UserAccountService (a total of 2), map the models to their associated view models, and return the data to the View.
On Line 22 we define the expected number of user accounts, whilst on Line 36 we assert that a ViewResult type has been returned upon acting. On Line 38, we assert that the data has been mapped to the associated view model, before finally asserting that the expected count is correct on Line 41.