Unit Testing Optimizely CMS 11
Published: 29th September 2018
The Requirement
I needed to implement a new visitor group criterion for an Optimizely CMS website. As part of this work I was introducing unit testing into the project and wanted to make sure that all of my new classes were unit tested.
The First Issue
I created a new criterion class (MyCustomCriterion) that inherited from CriterionBase and set about writing my tests. I set about writing tests and implementing logic and immediately hit a wall. Model is a property of CriterionBase
With the model now definable in the setup of a unit test, I set about writing my tests making them pass. I injected my dependencies via the constructor of MyCustomCriterion and soon I had working custom criterion that looked a little like this.
[VisitorGroupCriterion(Category = "My Category", DisplayName = "My Custom Criterion")]
public class MyCustomCriterion : CriterionBase<MyCustomCriterionSettings>
{
private readonly ICustomService service;
public MyCustomCriterion(ICustomService service)
{
this.service = service;
}
public override bool IsMatch(IPrincipal principal, HttpContextBase httpContext)
{
MyCustomCriterionSettings settings = Model;
// Some verification code to be tested
return result;
}
}
The Second Issue
All of the logic was correct, all the unit tests passed. In practice however, the MyCustomCriterion class caused the website to throw an error as any class inheriting from CriterionBase
In order to unit test a class using dependencies resolved with the ServiceLocator, you can create a mock of IServiceLocator and assign it to the static ServiceLocator class. You can then mock your other dependencies and set them to be returned by the mock IServiceLocator.
private Mock<IServiceLocator> mockServiceLocator;
private Mock<IDependencyUnderTest> mockDependency;
[SetUp]
public void Setup()
{
mockDependency = new Mock<IDependencyUnderTest>();
mockServiceLocator = new Mock<IServiceLocator>();
mockServiceLocator.Setup(x => x.GetInstance<IDependencyUnderTest>()).Returns(mockDependency.Object);
ServiceLocator.SetLocator(mockServiceLocator.Object);
}
[Test]
public void TestOne()
{
// Arrange
mockDependency.Setup(x => x.MethodUnderTest(It.IsAny<int>())).Returns(1001);
var criterion = new MyCustomCriterion();
criterion.Initialize(
new VisitorGroupCriterion
{
Model = new MyCustomCriterionSettings
{
Setting1 = 1,
Setting2 = "Two"
}
});
// Act
var isMatch = criterion.IsMatch(null, null);
// Assert
Assert.That(isMatch, Is.True);
}