Mocking the Content Repository
One of the most useful unit testing tools available to you as a developer is Moq. Moq is a lightweight mocking framework that will allow you to get a lot more test coverage in your projects. If you have never used a mocking framework it might be a little daunting at first but Moq is very easy to use.
Adding Moq To A Project
You can add Moq to your project, via Nuget. On your test project in visual studio, right-click on the project:
In Nuget, type Moq and add it, job done.
With the release of Episerver 7 and MVC, our lives are a lot more easier to unit test our codebase. In the dark and gloomy days of version 6, you had things like the Data factory that made life a lot more difficult to test properly. If you're reading this and you still don't really get it, then I'll try to give an example before we dig into the code. Say you use a page type to hold some metadata like a list of countries that you ship your products to.
You want to unit test your shopping basket, however, within the code, some logic exists that calls the Episerver API to check that the country has a matching entry in Episerver for validation purposes. Cool? You write your unit test and it throws an object reference exception when you make a call to the API to get the page. Why? When an Episerver loads a number of configurations and process-related values are set-up, this allows the API to work, iis to work and a whole host of other goodies. When you run your unit tests, these won't have access to them. Within your unit test you may have some code that works on your live site but throws an exception when you test it. To get over this dilemma, we can use mocks to fake the request to the Episerver database and return an object of our choosing.. enter mock. It creates a pretend object that your code thinks is a real object but allows you as a developer a lot more freedom.
One of the most frequent things you need to Mock are pages. Mocking a page is very easy, you create a page within Mock (in the same way you create a List<>). First, you use the Mock<> keyword and place the thing you want to mock as the type. To use the mocked object you need to call .Object() to get the correct type returned.
The code to mock a page is simple. Wrap the IContentRepository into mock and then use it via the .Object() method.
Mocking the Content Repository
Up next is mocking the Episerver API. The most used API is the content repository. This lets you do stuff with pages and blocks, like load, find and search.
Mocking Content Repository is also very easy; we pass the type of IContentRepository into the mock and then use it via the .Object() method.
Mocking Get<> Within the Content Repository
Now we have mocked the content repository, I'm guessing you will want to do some stuff with it. If you try and get a page from the mocked content repository, it will return null. As in the example mentioned above, you may have code that relies on a pages to be returned. When you run the code in a live environment, your code always returns a value, so we also need a way to repeat the same thing in your test environment.
To Moq a Get<> call, we first need to mock the page we want to return. In this example I'm using the It.IsAny() as the input parameter in my Setup method. This bit of code is tell Moq that a match exists when any content reference is passed in.
We then use a Returns() qualifier that tells Moq what to return when it finds a match. In this example the mocked page type. In case you're wondering how this will work in your unit test class, you would put the code above somewhere like your SetUp method and then in your unit test you would use this code to return your mocked page:
Mocking GetChildren<> Within Content Repository
So, now we have covered how to get a single page back from Episerver, let's move onto multiple pages:
In our code, we tell Moq that a valid match occurs when GetChildren is called with any Content Reference. Within a test, you could write code similar to this and you would get an enumerable list filtered by page type returned.
As we have just talked about GetChildren<> there may be situations when you want to return null. In your return, if you try to return null, your Moq will throw an exception as it won't know what constructor to use, instead of just returning null you need to return a type then null:
Checking An Interface Within A Method Has Been Called
Sometimes you may have some logic in your class that calls a dependency In some instances the dependency it's calling will have it's own setup unit tests so the main thing you care about is to have a confirmation that the inner class/dependency has been called. We can do this in Moq using both '.Verifiable()' and '.Verify()' methods.