Archive
Easy unit testing in Sitecore with AutoFixture, NSubstitute and Xunit
Unit testing Sitecore code has been around for quite som years now, and with the release of version 8.2 Sitecore has implemented a lot of new abstractions, which makes testing of Sitecore code easier. So if you not on 8.2 yet this might not be for you, or this could be a reason for upgrading to 8.2. Today there exists a couple of framework that will help developers with writing unit test to Sitecore one of the more known ones I Sitecore FakeDb. But as we shall see in the following a good portion of the more simple Sitecore API can easyli be test without, but creating test stubs can quick become a cumbersome tasks, and this is exactly where this post comes into play.
Let me briefly introduce AutoFixture
This is take from The AutoFixture Github pages https://github.com/AutoFixture/AutoFixture
AutoFixture is an open source library for .NET designed to minimize the ‘Arrange’ phase of your unit tests in order to maximize maintainability. Its primary goal is to allow developers to focus on what is being tested rather than how to setup the test scenario, by making it easier to create object graphs containing test data.
For me Autofixture helps me writing clean Tests where magic values, or test object are hidden away, ie dummy data is something created when the test runs. I strongly encourage you to take a deeper look at Autofixture it is an awesome Library
Okay so how does this combined with Xuint and NSubstitute. Today You can create an Subsitute for a Sitecore Item But it stille take quite som parameters to create the item so you need to create more than one Substitute see the example below.
var db = Substitute.For<Database>(); var itemId = ID.NewID; var language = Substitute.For<Language>(); var definition = new ItemDefinition( itemId, "itemname", ID.NewID, ID.NewID); var data = new ItemData( definition, language, Sitecore.Data.Version.First, new FieldList()); var item = Substitute.For<Item>(itemId, data, db); return item;
You could in your test have a test factory that just creates this object for you of course.
Enough Skip to the point .. okay lets see where you getting at.
Okay given the following class Which I want to test. All it does is, for the master database get the root item and add a ChildItem, with any TemplateId and return the newly created child.
public class MyClass { private readonly IFactory _factory; public MyClass(IFactory factory) { _factory = factory; } public Item AddToSitecore() { Database database = _factory.GetDatabase("master"); Item rootItem = database.GetItem("/sitecore/content/home"); Item childItem = rootItem.Add("child", new TemplateID(ID.NewID)); return childItem; } }
I can write the following test
using FluentAssertions; using NSubstitute; using Sitecore.Abstractions; using Sitecore.Data; using Sitecore.Data.Items; using Xunit; namespace Sitecore.AutoFixture.NSubstitute { public class MyClassTests { [Theory, AutoSitecoreData] public void MyClass_AddItemToWithAutoFixtureRoot_ShouldReturnItem(Item rootItem,Item childItem,Database database,IFactory factory) { //Arrange database.GetItem("/sitecore/content/home").Returns(rootItem); factory.GetDatabase("master").Returns(database); rootItem.Add(Arg.Any<string>(), Arg.Any<TemplateID>()).ReturnsForAnyArgs(childItem); MyClass sut = new MyClass(factory); //Act Item returnItem = sut.AddToSitecore(); //Assert returnItem.Should().NotBeNull(); returnItem.ID.Should().BeSameAs(childItem.ID); returnItem.Name.Should().BeEquivalentTo(childItem.Name); rootItem.Add(Arg.Any<string>(), Arg.Any<TemplateID>()).Received(); database.GetItem("/sitecore/content/home").Received(); } } }
What is nice here is you can the easy created Database and Items (root,and child), and a Sitecore Factory, you can set your expectations in your own test to match what you’re testing.
All with the help of the AutoSitecoreData Attribute that decorates the tests.
It magically creates new items, database, Sitecore factories, Settings, the last two fund in Sitecore Abstractions. No need for Factories, all you get is relevant data with out static items or
It’s not entirely magic, it extends some AutoFixture attributes, you can have a look at the code at Github
https://github.com/istern/Sitecore.AutoFixture.NSubstitute
There Are a few gotchas For this to work in your test, you need to get the code from Github and build it, Hopefully I will soon build a nuget package which will make this step obsolete . But once build you can reference the SitecoreAutoDataAttribute in your tests. You will also have to reference Sitecore.Kernel but no additional references to Sitecore files is required.
Hope you will find this useful