Sunday, December 9, 2012

Painless unit testing - sharepoint emulators


With the availability of Visual Studio 2012 SharePoint Emulators the isolation of the SharePoint API is much easier compared to the old way of isolating using the Moles or Fakes framework.
In order to incorporate emulators into existing tests you should wrap the relevant code in a SharePointEmulationScope, which accepts EmulationMode enum as a parameter. It is enabled by default which in turn performs run time interception of all Microsoft.SharePoint.dll calls.

You can use the new emulator in your unit test project by using nuget packaging manager and convert your old test case to the new emulation scope as given below

 [TestMethod]
public void BuildFromSPListItemShouldCreateANewObjectWithPopulatedValues()
{
    using(ShimsContext.Create())
    {
        var dataMapper = new MyObjectDataMapper();
        const string customDescription = "Custom Description";
        var spListItem = new ShimSPListItem
        {
            ItemGetString = (fieldName) =>
            {
                if (fieldName == BaseInternalFields.Id) return 1;
                if (fieldName == BaseInternalFields.Title)
                    return "Some Title";
                return fieldName == RulesInternalFields.CustomDesc
                    ? customDescription
                            : null;
            },
            FieldsGet = () => new ShimSPFieldCollection
            {
                ContainsFieldString =
                    (internalName) =>
                    internalName.Equals(BaseInternalFields.Id) ||
                    internalName.Equals(BaseInternalFields.Title) ||
                    internalName.Equals(RulesInternalFields.CustomDesc)
            }
        };

        var myObject = dataMapper.FromSPListItem(spListItem);
        Assert.IsTrue(myObject.CustomDesc == customDescription);
    }
}


[TestMethod]
public void BuildFromSPListItemShouldCreateANewObjectWithPopulatedValues ()
{
    using (var emulation = new SharePointEmulationScope(EmulationMode.Enabled))
    {
        var dataMapper = new MyObjectDataMapper();
        const string customDescription = "Custom Description";
        using(var emulatedSite = new SPSite("http://localhost:8081/MySite"))
        {
            var listId = emulatedSite.RootWeb.Lists.Add("MyList", "Custom list", SPListTemplateType.GenericList);
            var list = emulatedSite.RootWeb.Lists[listId];
            var listitem = list.Items.Add();
            listitem["Title"] = "mytitle";
            listitem["CustomDesc"] = "Custom Description";

            var myObject = dataMapper.FromSPListItem(listitem);
            Assert.IsTrue(myObject.CustomDesc == customDescription);
        }
    }
}

Because the emulator relies on the Fakes framework, you can easily reuse your existing code to use the emulators without much pain.


No comments: