Contact Us

Capturing issues early in the development cycle is essential to improve user experience on Sitecore website. Now, the question is how can one capture issues early in the Sitecore development cycle? While there are many ways to capture issues early in the development cycle, Unit Testing is the most preferred way to localize issues quickly. So, let's get started with the basic understanding of Unit testing.

What is Unit Testing?


Unit testing is the process of testing the smallest piece of functionality (the Unit) of code to see if it will work as expected. Unit testing helps to ensure that all the functionalities of the application work as expected. It also ensures that the code will continue to meet expectations over time. It is the first level of software testing. It also increases the code quality.

How Unit Testing increases Code Quality?


  • Unit testing helps in understanding the design and code-related changes. Thus, helps in writing good quality code/ improving the design by revealing architectural flaws.
  • Unit testing gives visual and instant feedback. Hence, one can refactor his/her code without waiting for deployment, test the functionality on the server and do the required updates.
  • Unit testing promotes modularity in design as it forces to use Dependency Injection (DI), Single Responsibility Principle (SRP), and Separation of Interface and Implementation techniques as these techniques make it easier to mock external dependencies and create proper unit tests.

Features and Benefits of Unit testing


Isolated/Independent

Tests one unit at a time.
Unit under test doesn't depend on the other to make test runs.

Self-Documenting

Makes code under test clear and concise.
Can be a reference for the usage of your class/method/etc.

Repeatable

Running multiple times yields the same result irrespective of the environment.

Fast

Allows quicker detection of issues before deployment.

Makes debugging easier

You can exercise any piece of code by running its matching unit test

When is Unit Testing Needed?


Unit testing is done during the development phase (coding phase) of the application by Sitecore developers. Methods can break if error handling is performed through it. Any method which can break is a good candidate to have a unit test. As we know, every line of the code can fail during enhancements.

Test-Driven Development (TDD) is another preferred approach widely adopted to obtain high-quality code. Development starts by writing unit test cases based on business rules, followed by software functionality development and then improves/updates the code to meet the defined unit test framework.

AAAs of Unit Testing


The AAA (Arrange-Act-Assert) pattern has become almost a standard across the industry. It suggests that one should divide the test method into three sections: Arrange, Act and Assert. Each of them is only responsible for the part after which they are named:

Arrange

In the Arrange section, you only have the code required to set up a specific test. Here, objects would be created, mocks setup (if you are using one) and potential expectations would be set.
Act

The invocation of the method being tested.
Exercise method under test.
Assert

On Assert, one can simply check if the expectations are met.
One logical assert per test.
[TestMethod]
public void AAAs ()  

     //Arrange  
    Setup Test.  
       
     //Act  
    Invoke the actual method.  
       
     //Assert   
    Check if the expectations were met.  
}  

MSTest: Visual Studio Unit Testing Framework


MSTest is Microsoft's tool is used for running tests of .NET applications (in particular, it can be used for unit testing). One can integrate MSTest tests to their test projects created using 'Unit Test Project' template and run them as part of their DevOps pipeline before every deployment.

Pros
1. MSTest ships with Visual Studio, so you have it right out of the box.
2. Pretty Neat: The preferred .NET pattern for unit tests is to have a test project for each feature or foundation project in your codebase. With MSTest, getting that setup is as easy as File->New Project. When you write a test, right-click on it and execute it to have your result displayed in the IDE.
3. This framework is the simplest of all other frameworks (Eg: xUnit, NUnit etc.), and uses an easy-to-understand method attribute structure (much like most testing frameworks) where you are able to add tags such as '[TestClass]' and '[TestMethod]' to your code in order to get testing.
Cons
1. One of the most frequent knocks on MSTest is around performance.
2. Interoperability: Microsoft makes it so you can integrate with other Microsoft/Visual Studio stuff, so making it work with third-party integrations would probably not rate as a priority though.

How to create MS Test project


To add MS-Test project to your solution:

Step 1: Right-click on the solution and select Add -> Add New Project, Select Visual C#, then choose Test, then select Unit Test Project.

img

MS Test Project

Step 2: Enter the Name of the test project, choose a location and select .Net Framework & click on Create.

img

MS Test Project

After creating the project, MSTest adds the below default class,

using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Project.UnitTests.TestClassName   

     [TestClass]   
    public class TestClassName  
     {   
          [TestMethod]  
          public void TestMethodname()   
          {  
               //Arrange  
                    //Act  
                    //Assert  
          }  
     }   
}  
The TestClass attribute denotes a class that contains unit tests. The TestMethod attribute indicates a test method in the test class. You may also want to include ExcludeFromCodeCoverage attribute to the test class, to ensure the code in this test class is ignored by Code Coverage tool (E.g.: Visual Studio Code Coverage, SonarCloud etc.)

Add a reference to your Main Project


After creating Test project, you have to add a reference to your main project that has the code which needs to be tested. For adding reference:

Step 1: Right-Click on Test Project created above and select Add Reference from References section.

img

Main Project Reference

Step 2: Choose your main project under Project tab.

img

Main Project Reference

Sitecore FakeDB


Sitecore FakeDB is a unit testing framework that facilitates test Sitecore items in the system memory. It helps in testing Sitecore content items by initializing them in memory instead of making calls to the actual Sitecore database. It is used as a substitute for real Sitecore with minimal logic.

Note: It is not recommended to run the whole Sitecore instance in the memory and Sitecore FakeDB being a unit testing framework, is not supposed to be used for integration testing.

Features & Benefits of Sitecore FakeDB


Content Management

Allows to create a comprehensive content tree representation, configure fields, add field value, languages, versions, security, locking, templates hierarchy and standard values.

Security

Enables mocking/substituting Authentication, Authorization, Role and RolesInRoles providers, switching Context User.

Configuration

Allows configuring Sitecore Settings for unit tests from the test method

Globalization

Allows creating fake localized texts for Translate.Text() methods

Content Search

Allows mocking/configuring Content Search Manager & Search Indexes

Media

Allows mocking/substituting Media Provider

Links/(Talks)

Allows mocking/substituting Link(Task) Database

How to install Sitecore FakeDB


Sitecore FakeDb is available as NuGet package. To install the framework, one can follow the steps mentioned below:

Step 1: Run the following command in the NuGet Package Manager Console:

PM> Install-Package Sitecore.FakeDb

Step 2: Add references to the following assemblies:

  • Sitecore.Kernel.dll
  • Sitecore.Logging.dll
  • Sitecore.Nexus.dll

Step 3: Add license.xml to the Unit Test Project by following one of the below options,

         Option 1: Copy the license.xml file to the root of your tests project

         Option 2: Modify the 'LicensePath' setting in the App.config file

     Note: If using NUnit 3.x, you will need to update the LicenseFile setting to /license.xml in the App.config while copying the license file to your test project root.

Step 4: In the test project App.config file, add/update the below line:

< !--   DATABASE TYPE
     For Sitecore versions prior to 8.2 should be 'Sitecore.Data.Database, Sitecore.Kernel'.   
    For Sitecore 8.2 and later should be 'Sitecore.Data.DefaultDatabase, Sitecore.Kernel'. -->  
<sc.variable name="databaseType" value="Sitecore.Data.DefaultDatabase, Sitecore.Kernel" />   

 

How to update Sitecore FakeDB Framework


To update the framework run the following command in Package Manager Console:

PM> Update-Package Sitecore.FakeDb

An Example of Sitecore Unit Test with MSTest and FakeDBSimplest of all:

[TestMethod]
public void GetProduct_Validate()   

     var expectedProductTitle = "Product Title";   
     var expectedProductID = "Product ID";   
     var expectedProductLink = "https://www.example.com";  
     using (var db = new Db("web")   
     {   
           new DbItem("home")   
          {  
                new DbItem("product") {   
                    { "Title", expectedProductTitle },   
                    { "ID", expectedProductID },   
                { "ProductLink", $" link linktype=\"external\" url=\"{expectedProductLink}\" />" } />" }   
          }  
     })   
     {   
           //Arrange  
           var productItem = db.GetItem("/sitecore/content/home/product");  
           using (RenderingContext.EnterContext(new Rendering(), productItem))  
          {  
                ContextService.Get().Push(new PageContext());   
               PageContext.Current.Item = productItem;   
                 
               //Act   
               Product actualProduct = _productRepository.GetProduct();  
                 
               //Assert   
                Assert.AreEqual(expectedProductTitle, actualProduct.Title);   
                Assert.AreEqual(expectedProductID, actualProduct.ID);  
                Assert.AreEqual(expectedProductLink, actualProduct.Link);   
          }  
     }   
}  
Need Help?