Sitecore Unit Testing Guide — Part 1 : The Basics

Ehsan
5 min readJun 12, 2022

--

Find the source code here : https://github.com/ehsanaslani/SitecoreUnitTesting

Writing unit tests could be tricky sometimes and unit testing Sitecore solutions, introduces its own kind of challenges. In these series of articles I will try to explain about unit testing Sitecore solutions and address the challenges faced by developers in writing tests. I hope that this guide can help developers to make unit testing an enjoyable experience.

Let’s start

In the first part let’s start with the basics of writing Sitecore unit tests. It is assumed that the reader has basic knowledge about unit tests as it’s needed to understand the contents.

In the examples and the companion source code, I have used Xunit, Nsubstitute, FluentAssertions libraries but of course the principles can be used with any other frameworks of your preference

How to write unit tests?

To write useful and high quality unit tests, which can be maintained and understood by others, keep these standard best practices in mind:

  • Choose descriptive names for your tests: Your tests should be readable for other developers looking at your tests. Unit tests also serve as a documentation for your code. Use a naming convention which can describe the subject of test, the scenario and the expected result and follow the convention in all your tests. You can see some of the common naming conventions here
  • Your tests should only test the unit under test: When you are testing a class that has dependencies, your test should only test that class and not the dependencies. Use mocking frameworks to mock all the dependencies.
  • Write independent tests: Don’t write tests that depend on each other. Each of your tests should not be aware of existence of other tests and should not depend on them
  • Write stable tests : Your tests should only fail if there is a bug in the code. So make sure that they don’t fail because of the running conditions. For example keep in mind that your tests will be run in parallel with other tests and make sure tests will not fail when executed with others. This can happen if your tests modify static members that other tests use it.
  • Write short and readable tests: Long unit tests with several lines could be difficult to read and are difficult to maintain as well. Keep them as short as possible.
  • Do not use multiple assertions in a single test: Each test should only test one scenario and ideally one assertion. This makes it more readable and maintainable. Whenever you find yourself adding multiple assertions in a test consider breaking it into multiple separate tests.
  • Follow the AAA pattern : Your tests should simply have three sections. Arrange, Act and Assert. Arrange the test data, Act the function that is going to be tested and Assert the expected results.
  • Do not use conditions and loops in your tests: Your test should not include conditions (if & switch statements), loops (while, for, foreach). If your test includes these statements, it’s probably a sign that it can be broken into few smaller tests.

Mocking Items, Templates and Databases

Your code for Sitecore solutions will normally use Items, Templates and Databases a lot. As we don’t want to retrieve actual items from databases, you need to mock them. Mocking is a way to fake the dependencies of the systems under test and testing it in isolation. There are several mocking frameworks such as NSubstitute and NMock that you can use to create fake objects. When you mock a dependency like an Item or Template, you can define its behavior to simulate your test scenario.

You can’t mock concrete classes. You can only mock interfaces, abstract classes or partially mock concrete classes that have abstract or virtual members. The good news is that Sitecore uses those abstractions and therefore it’s mostly mockable:

  • Database class is an abstract class
  • Public members of Item & Field classes are virtual
  • Public members of TemplateItem class are virtual

This means that you can easily create mock objects for these classes and define how they should behave during test. Let’s see an example:

Let’s try to unit test this simplified piece of code:

We want to make sure that the method does not throw exception if the Age field does not have a valid integer value (as you can guess, this test should fail). So we need to provide a mock item for the personData that has a child item with an invalid integer value in it’s age field.

GetMockItem method creates a mock item object using the Substitute.For<>. Item class constructor expects three parameters : Item ID, an ItemData instance and a Database instance which are passed to it through the For<> method parameters. Item fields are also mocked by setting a mock FiledCollection object.

AddField method, first creates a mock Field object and then sets the behavior so it return the specified value when Field.Value is called. then the Field[ID] and Item[String] indexers are mocked. Remember that we fed a mocked FieldCollection when mocking the item, so we can use the Returns method in Item.Fields to define its behavior.

Now let’s take a look at another simplistic example. This method tries to get the value of “Page Category” field of the current page and if it’s not set, it will return the default value which is set in another item in the database:

so let’s write a unit test to make sure that this method will return the default value if the category is not set:

In this test, we create the mock items for the context page and the default data item, then the database GetItem is wired to return the default data item and finally the Context item and database is set.

Next Steps

Although these tests work well, there is still room for improvement. In next part we will look into the ways to make the tests shorter and more readable and ways to reuse the mocking code in our tests to avoid repeating them across our test classes.

--

--

Ehsan

I’m a software architect specialized in Sitecore content management solutions