Tuesday, March 8, 2016

Unit Testing in EpiServer using Moq

Regardless of what do you think about TDD (Test Driven Development)  there are many scenarios that you want to implement an automatic testing in your code. But how do we implement tests in a CMS like EpiServer?
As a basic step, one has to mock some behaviors in EpiServer services like ContentRepository, ContentProviderManager, etrc. To do so, you have to create a mock object from that interface and then use that mock instead of real object. For instance we can do these steps using Moq library:

1- Create a mock for the service that you want to use
for instance you can create a mock for content loader. This class has been used to load contents from EpiServer, like when you want to load and use a specific page (like setting page) or content.
Code:
var mockContentLoader = new Mock<IContentLoader>();
 2- Mock methods that you need
now you have to tell Moq what you want to return instead of the normal behavior.

We can ask for a general behavior like returning an object if there was a request for a type. like
Code:
mockContentLoader.Setup(r => r.Get<StartPage>(It.IsAny<ContentReference>())).Returns(new StartPage());
this code will return a new StartPage when someone uses ContetnLoader.Get<StartPage> method, with any ContentReference.
    Or we can mock an specific request like
    Code:
    mockContentLoader.Setup(r => r.Get<StartPage>(myStartPage.ContentLink)).Returns(myStartPage);
    This code will return your startpage if there is a request with it's content link. Pretty similar to how you code on EpiServer :)
    3-Use the mocked class
    To use the class that you mocked, you need an object from it. For instance, when you want to test a class that need your ContentLoader you can do it like this:
    Code:
    var myServiceToTest = new MyService(mockContentLoader.Object);
    Now you can use your class/service and whenever it wants to use the content loader, it will have the mocked results instead of trying to call DB or etc. :)

    *If you want to use the injection in your code, you have to  create a new mock for ServiceLocator, or get it if you already have it.
    To create a new one use this:
    Code:
                var mockLocator = new Mock<IServiceLocator>();
    To get the existing one use
    Code:
    var mockLocator = Mock.Get<IServiceLocator>(ServiceLocator.Current);
    Now you can easily use the same concept and return your mocked class easily
    Code:
    mockLocator.Setup(l => l.GetInstance<IContentLoader>()).Returns(mockContentLoader.Object);
    You just need to remember to set the new serviceLocator
    Code:
    ServiceLocator.SetLocator(serviceLocator.Object);
     To read more about Moq go to this page

    2 comments:

    1. what references to my test project i need to be able to read IContentLoader/Repository in test project?

      ReplyDelete
    2. you need a reference to EPiServer, you can select it from "Add reference -> Browse -> EPiServer.dll

      ReplyDelete