Introducing SharePoint Emulators

Introducing SharePoint Emulators

Rate This
  • Comments 12

The Visual Studio team is pleased to announce availability of Visual Studio 2012 SharePoint Emulators. Unit testing for SharePoint code is difficult. Ideally you would like to isolate code under test from the surrounding SharePoint framework. Isolation frameworks, such as Microsoft Fakes, can enable this code isolation. Unfortunately, as anyone who has followed this path will tell you, creating and maintaining the set of mocks and fakes for the SharePoint environment can be very costly. Luckily, the SharePoint Emulators team has done the heavy lifting for you. SharePoint Emulators provide a system of Fakes based shims implementing the basic behaviors of the SharePoint 2010 server object model.

System Requirements

· Microsoft SharePoint 2010 Server (SharePoint 2010 Server or SharePoint 2010 Foundation)

· Microsoft Visual Studio 2012 Ultimate

Getting SharePoint Emulators

SharePoint Emulators are available today through a NuGet package feed. Perform a simple search of the NuGet official feed for “SharePoint Emulators”.

clip_image001

Using SharePoint Emulators

SharePoint Emulators are easy to incorporate into existing tests. You can write tests against the SharePoint Emulators using only the SharePoint API. All that is needed is the wrapping of test code in a SharePointEmulationScope.

[TestMethod]     
public  void ScheduleAppointmentReturnsTrueWhenNewAppointmentIsCreated()     
{     
    using (new SharePointEmulationScope(EmulationMode.Enabled))     
    {     
        SPSite site = new SPSite("
http://localhost");   
        string listName = String.Format("List{0}", Guid.NewGuid());

        // create a new temporary list     
        Guid listId = site.RootWeb.Lists.Add listName, listName, 
                      SPListTemplateType.GenericList);
     
       
SPList list = site.RootWeb.Lists[listId];     
        Assert.IsNotNull(list);

        // add fields to list     
        list.Fields.Add("Name", SPFieldType.Text, true);     
        list.Fields.Add("Phone", SPFieldType.Text, false);     
        list.Fields.Add("Email", SPFieldType.Text, false);     
        list.Fields.Add("Age", SPFieldType.Text, false);     
        list.Fields.Add("Date", SPFieldType.Text, false);
        list.Update();

        // prepare
        string errorMsg = string.Empty;
        DateTime date = DateTime.Now;
        BookAnAppointmentWebPart webPart = new BookAnAppointmentWebPart();

        // act
        bool success = webPart.ScheduleAppointment(site.RootWeb, list.Title, "My Name",
                       "888-888-8888", "My.Name@contoso.com", "23", date, out errorMsg);

        // assert
        Assert.IsTrue(success);

        // cleanup
        list.Delete();
        site.Dispose();
    }
}

All code wrapped within a SharePointEmulationScope will be automatically detoured at runtime. All calls against the Microsoft.SharePoint.dll assembly will be rerouted to the SharePoint Emulators.

Extending SharePoint Emulators

Due to the wide size and scope of the SharePoint API surface we focused on the types and methods most highly used. Using a type that has not been implemented results in a little bit of extra work to get the test passing.  As an example the following test fails, with an unimplemented exception.

[TestMethod]
public void GetAppointmentsForTodayReturnsTwoAppointments()
{    
    using (var emulationScope = new SharePointEmulationScope(EmulationMode.Enabled))    
    {    
        SPSite site = new SPSite("
http://localhost");  
        string listName = String.Format("List{0}", Guid.NewGuid());

        // create a new temporary list    
        Guid listId = site.RootWeb.Lists.Add(listName, listName,    
        SPListTemplateType.GenericList);     
        SPList list = site.RootWeb.Lists[listId];     
        Assert.IsNotNull(list);

        // add fields to list     
        list.Fields.Add("Name", SPFieldType.Text, true);     
        list.Fields.Add("Phone", SPFieldType.Text, false);     
        list.Fields.Add("Email", SPFieldType.Text, false);     
        list.Fields.Add("Age", SPFieldType.Text, false);     
        list.Fields.Add("Date", SPFieldType.Text, false);     
        list.Update();

        DateTime date = DateTime.Now;     
        BookAnAppointmentWebPart webPart = new BookAnAppointmentWebPart();

        // insert 3 item into list     
        SPItem item = list.Items.Add();     
        item["Name"] = "My Name";     
        item["Phone"] = "888-888-8888";     
        item["Email"] = "My.Name@contoso.com";     
        item["Age"] = "23";     
        item["Date"] = date.ToString("D");     
        item.Update();

        SPItem item2 = list.Items.Add();     
        item2["Name"] = "His Name";     
        item2["Phone"] = "777-777-7777";     
        item2["Email"] = "His.Name@contoso.com";     
        item2["Age"] = "25";     
        item2["Date"] = date.AddDays(1).ToString("D");     
        item2.Update();

        // Act     
        string result = webPart.GetAppointmentsForToday(list.Title, site.RootWeb);

        // Assert     
        Assert.IsTrue(result.Contains(String.Format("Name: My Name, Phone: 888-888-8888,
               Email: My.Name@contoso.com, Age: 23, Date: {0}", date.ToString("D"))));    
        Assert.IsFalse(result.Contains("Name: His Name"));

        // cleanup    
        list.Delete();    
        site.Dispose();    
    }    
}

 clip_image003

 

If you do find an area not covered, it is straightforward to extend and implement new emulated behavior. SharePoint Emulators rely entirely on the Microsoft Fakes framework. They consist of only concrete implementations of shims. When encountering an unimplemented shim all that is needed is to provide a implementation of that shim. The details of the shim that is required is detailed in the error message, in this example SPList.GetItems(SPQuery).

if (emulationScope.EmulationMode == EmulationMode.Enabled)    
{    
    var sList = new ShimSPList(list);    
    sList.GetItemsSPQuery = (query) =>    
    {    
        var shim = new ShimSPListItemCollection();    
        shim.Bind(new[] { list.Items[0] });    
        return shim.Instance;    
    };    
}

The addition of this code to the previous test allows it to pass. You can use this technique to implement missing behavior or to customize Emulators to match your own environment.

Running Multi-Target Tests

Running tests against the Emulators provides many advantages: performance improvements, isolation from SharePoint, and reduced maintenance of test SharePoint infrastructure. However, there are times when you still want to run tests against a real SharePoint server. SharePoint emulators enables the reuse of the same test code, but run in different context.

The SharePointEmulationScope takes as a parameter an optional EmulationMode enum. The default enabled mode performs run time interception of all Microsoft.SharePoint.dll calls. The second passthrough value allows all calls to bypass all shims and directly call into the original assembly. The use of this enum value can control the context of test execution.

There are numerous ways of consuming and controlling this EmulationMode value. The SharePoint emulator team is fond of Data Driven tests to control the EmulationMode. In this way the test team is able to write tests that work against the SharePoint Emulators and the default SharePoint server. We use these tests and this approach to verify the behavior of the SharePoint Emulators. There are lots of alternatives for usage: setup and initialization code, preprocessor directives, ect.

 

Resources

Leave a Comment
  • Please add 8 and 3 and type the answer here:
  • Post
  • Such a pity this is Ultimate only....would have loved to try this out

  • Really fantastic!!!

  • In the first code listing is "BookAnAppointmentWebPart" supposed to be part of the Emulator package?  When I copied and pasted the code I could not get it to run.

  • @Gary A. Bushey.

    The "BookAnAppointmentWebPart" is a sample code snippet from a sample app. The code is not part of the Emulator package and not intended to be able to be run. It is simply to demonstrate the concepts. Hope this helps.

    Joshua Weber

  • That is really what we need ! When will we have a version for SharePoint 2013 ?

  • nice addition to SP toolset. However seems that some stuff will be really hard to implement: for instance, universal SQPQuery handler requires custom CAML parser :( so we'll need to reimplement GetItems shim for every SPQuery.

    Anyway, good job! thanks to VS team.

  • Obvious question... what about SharePoint 2013 support?

  • Are there any hidden dependencies we need to know ?

    I don't want to install SP on my build server ;)

  • Any plans for these to be available for Premium?

  • Since Fakes & Shims were included in Premium with Update 2 it would be nice to see this included as well!

  • SP2013 support docx here: download.microsoft.com/.../Testing%20and%20Debugging%20SharePoint%20Applications%20with%20Visual%20Studio%202013.docx

  • You can use SPEmulators for ShrePoint 2013. The SPEmulators package is available on nuget. See writeabout.net/.../spemulators-available-on-nuget

Page 1 of 1 (12 items)