In this tutorial, you will learn some tips that will help you use Moq to unit test Episerver CMS-powered code. 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, introducing one in your codebase might be a little daunting at first, however, Moq is very easy to learn and implement within your project. After a few hours, you will be a pro!

How To Install Moq Within Episerver

You can add Moq to your project, via NuGet. On your test project in visual studio, right-click on the project:

How To Use Moq To Unit Test Episerver 1

In Nuget, type Moq, select it from the list and install it:

setting_up_moq_nuget

Job done ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ

Mocking Episerver

With the release of Episerver 7 and MVC, it is now possible to easily unit test our codebase. In the dark and gloomy days of version 6, Episerver used APIs like the data factory. The data factory used a singleton pattern to access CMS content. These types of APIs made it a lot more difficult and time-consuming to unit test Episerver code. The reason why these APIs made testing close to impossible was because they all required the HTTP context to exist and a valid database connection to work. If you tried to test a method that used the data factory in code when the test ran it would throw an object reference exception. To test code that will not work in the unit test, you can Moq it. Mocked objects are dummy objects that your code will think is the real deal. The mocked object can be configured how you see fit. Using mocks means you can test code that was not previously possible. The caveat is that the code you are trying to mock really needs to implement an interface. Luckily, almost all the APIs in Episerver 7 do... so happy days ๐Ÿ˜Š

Mocking Pages

One of the most frequent things you need to mock in Episerver is content pages. Mocking a page is very easy with Moq. First, you use the Mock keyword and place the thing you want to mock as the type T. To use the mocked object you need to call a method names .Object() on the mock. This will return a dummy mocked instance object:

As you can see, the code to mock an Episerver page is pretty simple. With your mocked object, you can then configure it to return any test data that you choose! Up next is mocking the Episerver API.

Mocking the Content Repository

To access a CMS page in code you will normally use the IContentRepository. This API lets you do stuff with pages and blocks, like load and save data to the CMS. To code the mock the IContentRepository is also simple:

Mocking the content repository is also very easy. We pass the type of IContentRepository into the mock and then use the .Object() method to get the mocked representation!

Mocking Get<> Within the Content Repository

If you try and get a page from the object created by Moq without doing any configuration, it will return null. If you wanted to use this default mock repository to query a page within the CMS, this test would fail. After mocking an object, in a lot of situations you also need to configure the mock to return the correct test data:

To mock 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:

Using this code you can now return a single page from the mocked object when it is accessed. Next, let us mock returning multiple pages!

Mocking GetChildren Within Content Repository

To mock multiple pages you will need to use the content repositories GetChildren<T>() method:

In our code, we tell Moq that a valid match occurs when GetChildren() is called and Any type of ContentReference is passed into it. If you want to be more specific about the values of the content reference you can. For most tests using Any is a quick and easy approach to get a test working. Within a test, you could write code similar to this and you would get an enumerable list of pages returned:

Returning Nulls

There may be situations when you want to return null from an API call. For example, to test an unhappy path. If you try to return null you will bump into an issue. Moq will throw an exception as it won't know what constructor to use in GetChildren(). To return null you also need to type it:

Checking An Interface Within A Method Has Been Called

Sometimes you may have some logic in your class that calls one or more additional dependencies. Good practice unit testing advice is to only test the logic in the method that you are testing. You do not want to test code in additional dependencies. Doing this will create a test maintenance nightmare. If you try to test more than the class under test, you will end up with flakey tests. When you make small code tweaks in your codebase you will notice lots of unit tests in code that is not directly relevant to your class suddenly break. This is why when unit testing all you need to test is that all the inner dependencies in the class under test have been called with the data you expect and nothing more. Never test at a deeper level than this, unless you want to end up in test hell๐Ÿ”ฅ. We can do this in Moq using the .Verifiable() and .Verify() methods:


You should now hopefully be an Episerver Moq master... Happy Coding ๐Ÿค˜