Sitecore 8.2: Mock your Items
Back in January I wrote an article about how to Roll your own Sitecore Item, which showed how to create an in-memory Sitecore item for use in testing. The technique was quite limited and still required some small config entry to allow everything to work (to create a Database instance). Well, Sitecore 8.2 has finally made a reality what so many of us have prayed for, for so long. We can finally mock Items and Databases with Sitecore 8.2. Though, it’s probably not quite as simple as you might hope.
Keep in mind, items aren’t DTOs to be newed up here and there. An Item is instantiated within the data layer, so it doesn’t have a parameterless constructor, which is required by many mocking frameworks. To mock an Item, we still need the arguments for it’s constructor. So here’s the minimal code to mock an Item. Note how we can mock the DB now. BTW, I’m using Moq as my mocking framework.
var id = ID.NewID;
item there is not a real Item, it’s a mocked item! And because we’re mocking, and all the Item members are now virtual, we can use setups to configure member behavior. This allows us to fill in gaps from the previous technique like accessing fields by name.
itemMock.SetupGet(x => x["field"]).Returns("value");
Or how about accessing the content tree? We’ll need a few mock items for this setup, so let’s wrap up the above code in a utility method we can call to create a mocked item named
CreateMockedItem(). Now we can setup the
Children property to return a list of mocked items:
var item = itemMock.Object;
How about creating items? We can setup the
Add() method to return a mocked item as well:
var addedItem = CreateMockedItem();
OK, lot’s of good stuff there. But not all scenarios only use direct members of the item. Some scenarios we’ll want to run will need to mock objects which the item exposes. Let’s access the name of the item’s template. The
Template property of the
Item gives us access to the template and the
Name property hangs off that (Let’s ignore the
TemplateName property of
Item for a second). We’ll need to mock the template, and then mock
Template access on the
Item to return the mocked template:
var fakeTemplateItem = CreateMockedItem();
So yeah, we’ve got the ability to mock an Item. But given how much code we need to write to fulfill many scenarios, perhaps mocking isn’t always what we’re after. FakeDB still makes plenty of scenarios much easier to implement with less code than when we mock everything ourselves. So add Item mocking to your toolbox. Just remember to use the right tool for the job.