Loading...

Sample unit tests for a Sitecore pipeline

Just because we can't mock a custom Sitecore pipeline doesn't mean we can't write a unit test for it. Below is sample code for a custom NotFound404Processor Sitecore pipeline and couple of sample unit tests written for it. Moq v4.5.23 is used as the mocking framework.

Our starting point is NotFound404Processor as talked about in CUSTOM SITECORE 404 PAGE IN A CONTROLLER AND WRITING A UNIT TEST article. You can read more about the 404 page implementation there.

Let's go

First thing we do is modify NotFound404Processor so we can unit test it. We also create additional SitecoreContextArgs class which will be used to mock data in unit tests.

NotFound404Processor (modified)

Here is the modified NotFound404Processor. We do have a new ProcessNotFound404 method which retrieves the ErrorPage item if conditions are met. 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;

using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Pipelines.HttpRequest;
using Sitecore.Diagnostics;
using Glass.Mapper.Sc;
using Local.Sitecore.Domain.Wrappers;

namespace Local.Sitecore.Domain.Pipelines
{
    public class NotFound404Processor : HttpRequestProcessor
    {
        private readonly ISitecoreContext _sitecoreContext;

        public NotFound404Processor()
            : this(new SitecoreContext(Context.Database))
        { }

        public NotFound404Processor(ISitecoreContext sitecoreContext)
        {
            _sitecoreContext = sitecoreContext;
        }

        public override void Process(HttpRequestArgs args)
        {
            // Asserts that the arguments are not null
            Assert.ArgumentNotNull(args, "args");

            // get 404 item
            var notFoundItem = ProcessNotFound404(new SitecoreContextArgs(), Consts.NotFoundItemId);

            if (notFoundItem == null) return;

            // set current sitecore context item
            Context.Item = Context.Database.GetItem(new ID(notFoundItem.Id));
        }

        public ErrorPage ProcessNotFound404(ISitecoreContextArgs contextArgs, Guid notFoundItemId)
        {
            // ensure we are good to proceed
            if (contextArgs.CurrentItemExists 
                || !contextArgs.CurrentSiteExists
                || !contextArgs.CurrentDatabaseExists) return null;

            return _sitecoreContext.GetItem<ErrorPage>(notFoundItemId);
        }
    }
}

ISitecoreContextArgs

This interface contains properties used as conditions in the if-statement in the ProcessNotFound404 method. Using Moq we can mock these properties in our unit tests.


using Glass.Mapper.Sc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Sitecore;
using Sitecore.Sites;
using Sitecore.Data.Items;
using Sitecore.Data;

namespace Local.Sitecore.Domain.Wrappers
{
    public interface ISitecoreContextArgs
    {
        bool CurrentSiteExists { get; }
        bool CurrentItemExists { get; }
        bool CurrentDatabaseExists { get; }
    }

    public class SitecoreContextArgs : ISitecoreContextArgs
    {
        public bool CurrentItemExists
        {
            get
            {
                return Context.Item != null;
            }
        }

        public bool CurrentDatabaseExists
        {
            get
            {
                return Context.Database != null;
            }
        }

        public bool CurrentSiteExists
        {
            get
            {
                return Context.Site != null;
            }
        }
    }
}

NotFound404ProcessorUnitTests

Here are couple of unit tests for our pipeline.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Glass.Mapper.Sc;
using Glass.Mapper.Sc.Web;
using Local.Sitecore.Domain.Pipelines;
using Local.Sitecore.Domain.Wrappers;
using Sitecore.Data.Items;

namespace Local.Sitecore.UnitTests.Pipelines
{
    [TestClass]
    public class NotFound404ProcessorUnitTests
    {
        [TestMethod]
        public void ProcessNotFound404_IfNotCurrentSiteExists_ErrorPageIsNull_True()
        {
            // ------------------------------------------
            // ARRANGE
            Mock<ISitecoreContext> mockSitecoreContext = new Mock<ISitecoreContext>();
            mockSitecoreContext
                .Setup(x => x.GetItem<ErrorPage>(Guid.Empty, false, false))
                .Returns(new ErrorPage());

            Mock<ISitecoreContextArgs> mockSitecoreContextArgs = new Mock<ISitecoreContextArgs>();
            mockSitecoreContextArgs
                .Setup(x => x.CurrentItemExists)
                    .Returns(false);
            mockSitecoreContextArgs
                .Setup(x => x.CurrentSiteExists)
                    .Returns(false);
            mockSitecoreContextArgs
                .Setup(x => x.CurrentDatabaseExists)
                    .Returns(true);

            NotFound404Processor processor = new NotFound404Processor(mockSitecoreContext.Object);

            // ------------------------------------------
            // ACT
            var result = processor.ProcessNotFound404(mockSitecoreContextArgs.Object, Guid.Empty) as ErrorPage;

            // ------------------------------------------
            // ASSERT
            Assert.IsNull(result);
        }

        [TestMethod]
        public void ProcessNotFound404_IfNotCurrentDatabaseExists_ErrorPageIsNull_True()
        {
            // ------------------------------------------
            // ARRANGE
            Mock<ISitecoreContext> mockSitecoreContext = new Mock<ISitecoreContext>();
            mockSitecoreContext
                .Setup(x => x.GetItem<ErrorPage>(Guid.Empty, false, false))
                .Returns(new ErrorPage());

            Mock<ISitecoreContextArgs> mockSitecoreContextArgs = new Mock<ISitecoreContextArgs>();
            mockSitecoreContextArgs
                .Setup(x => x.CurrentItemExists)
                    .Returns(false);
            mockSitecoreContextArgs
                .Setup(x => x.CurrentSiteExists)
                    .Returns(true);
            mockSitecoreContextArgs
                .Setup(x => x.CurrentDatabaseExists)
                    .Returns(false);

            NotFound404Processor processor = new NotFound404Processor(mockSitecoreContext.Object);

            // ------------------------------------------
            // ACT
            var result = processor.ProcessNotFound404(mockSitecoreContextArgs.Object, Guid.Empty) as ErrorPage;

            // ------------------------------------------
            // ASSERT
            Assert.IsNull(result);
        }

        [TestMethod]
        public void ProcessNotFound404_IfCurrentItemExists_ErrorPageIsNull_True()
        {
            // ------------------------------------------
            // ARRANGE
            Mock<ISitecoreContext> mockSitecoreContext = new Mock<ISitecoreContext>();
            mockSitecoreContext
                .Setup(x => x.GetItem<ErrorPage>(Guid.Empty, false, false))
                .Returns(new ErrorPage());

            Mock<ISitecoreContextArgs> mockSitecoreContextArgs = new Mock<ISitecoreContextArgs>();
            mockSitecoreContextArgs
                .Setup(x => x.CurrentItemExists)
                    .Returns(true);
            mockSitecoreContextArgs
                .Setup(x => x.CurrentSiteExists)
                    .Returns(true);
            mockSitecoreContextArgs
                .Setup(x => x.CurrentDatabaseExists)
                    .Returns(true);

            NotFound404Processor processor = new NotFound404Processor(mockSitecoreContext.Object);

            // ------------------------------------------
            // ACT
            var result = processor.ProcessNotFound404(mockSitecoreContextArgs.Object, Guid.Empty) as ErrorPage;

            // ------------------------------------------
            // ASSERT
            Assert.IsNull(result);
        }
    }
}

The purpose of this article is to give you a quick overview (and hopefully some ideas) of how to unit test a custom Sitecore pipleline and it is not meant to be a detailed explanation of unit testing in Sitecore.

Let me know if you have any questions :)

Disclaimer
This is a personal blog. The opinions expressed here represent my own and not those of people, institutions or organizations that the owner may or may not be associated with in professional or personal capacity, unless explicitly stated.. In addition, my thoughts and opinions change from time to time I consider this a necessary consequence of having an open mind. This blog disclaimer is subject to change at anytime without notifications.