Sitecore.FakeDb - A Primer

I've been working a lot with the Sitecore CMS recently, focusing mainly in the realm of testing content and code and in my findings I've stumbled upon a little gem of a project that's quickly gaining popularity amongst the Sitecore community called Sitecore.FakeDb.

The premise of Sitecore.FakeDb is pretty simple - it creates an in-memory Sitecore database and allows you to fill it with mock items, fully customizable with mock fields, languages and templates. The problem it solves is that the Sitecore API you get out-of-the-box isn't abstractable in any way and is mainly devoid of interfaces so creating unit tests becomes a problem usually solved by creating wrappers around common classes such as Sitecore.Data.Items.Item and Sitecore.Data.Database.

I've found that using the combination of Sitecore.FakeDb to control the state of the data in the system and Glass Mapper to control the current context of the system (more posts on that later!), we gain a strong layer of abstraction that allows us to create strong, easy-to-write tests.

Setup

Getting up and running with FakeDb is a cinch - just install the package via Nuget and link your Sitecore license.xml file to the root of your unit test project like so:

Example

As long as you've got your test framework of choice set up, you're good to get going on your first test. To create a new in-memory database, you must instantiate a new Db() object but note that it does implement IDisposable so best practice is to either wrap its usage in a using{} block or explictly call .Dispose() after use.

To fill your mock database with mock items, instantiate as many DbItem() objects as you wish by passing in a name but you may also create items with an explicit ID and template ID as well.

Examples
Item item = null;

using(var mockDb = new Db())  
{
     DbItem mockItem = new DbItem("home", ID.NewID, null);
     mockDb.Add(mockItem);
     item = mockDb.GetItem("home");
}

Assert.IsNotNull(item);  

Here's a helper file I set up to use with FakeDb to have my test classes derive from that need mock Item data. This way you don't have to write code to handle the construction/destruction of the database in every testing class so you can do class PricingControllerTests : MockSitecoreDbFixture

namespace FakeDb.ExampleTests  
{
    [TestFixture]
    internal abstract class MockSitecoreDbFixture
    {
        [SetUp]
        public void SetUp()
        {
            _mockDb = new Sitecore.FakeDb.Db();
        }

        [TearDown]
        public void TearDown()
        {
            if(_mockDb != null)
            {
                _mockDb.Dispose();
                _mockDb = null;
            }
        }

        public Sitecore.Data.Items.Item Create(string name, ID id = ID.NewID)
        {
            return Create(new DbItem(name, id));
        }


        public Sitecore.Data.Items.Item Create(DbItem item)
        {
            _mockDb.Add(item);
            return _mockDb.GetItem(item.ID);
        }


        #region Private Members / Methods

        protected Sitecore.FakeDb.Db _mockDb;

        #endregion
    }
}
Conclusion

The project's wiki has a bunch more examples on how to set up your database to best represent the data you want to test. I'll be adding more posts soon focusing on more advanced usages of FakeDb such as writing integration tests between pipelines and using the AutoFixture and Serialization modules to create useful data quickly without adding any clutter to your test code.

I've also created a quick slideshow to present this information to coworkers that goes over a few more basic examples and usages here:

If you have any questions or just want to share your experiences with FakeDb, feel free to shoot me a message on Twitter @RollForReflex