Testing SharePoint – Now Easier with the New API

As I mentioned in my previous post on Unit Testing SharePoint , the Pattern and Practices group now use Typemock Isolator for their SharePoint Guidance tests. With the recent progress we do in our development, I took one of their tests, which use Natural Mocks, and translated it into AAA new API.

Let’s look at the original test (which is bundled with the Microsoft SharePoint guidance package):

public void CanAdd_NaturalMocks()
SPWeb web = this.RecordAdd();

Registration registration = new Registration();
registration.Title = "UnitTest";
registration.CourseId = 1234;
registration.UserId = 100;
registration.RegistrationStatus = "Pending";

RegistrationRepository repository = new RegistrationRepository();
int id = repository.Add(registration, false, web);

Assert.AreEqual(1, id);

Which calls the RecordAdd() method that contains the expectations:

private SPWeb RecordAdd()
SPWeb web = RecorderManager.CreateMockedObject<SPWeb>();
SPUser user = RecorderManager.CreateMockedObject<SPUser>();
SPListItem item = RecorderManager.CreateMockedObject<SPListItem>();

using (RecordExpectations recorder = RecorderManager.StartRecording())
recorder.ExpectAndReturn(web.SiteUsers.GetByID(1), user);
recorder.ExpectAndReturn(web.Lists[Lists.Registrations].Items.Add(), item);
item[Fields.Title] = "UnitTest";
item[Fields.CourseId] = 1234;
item[Fields.UserId] = 100;
item[Fields.User] = user;
item[Fields.Status] = "Pending";
web.AllowUnsafeUpdates = true;
web.AllowUnsafeUpdates = false;
recorder.ExpectAndReturn(item[Fields.Id], 1);

return web;

The expectations are based around the hierarchical model of SharePoint objects. The bulk of the expectations are meant to check the expectations. Let’s look at how the test looks now with the AAA syntax:

public void RepositoryAdd_FakeSPServer_PropertiesAreSetWithCorrectArguments()
var fakeWeb = Isolate.Fake.Instance<SPWeb>(Members.ReturnRecursiveFakes);
var fakeUser = fakeWeb.SiteUsers.GetByID(1);
var fakeItem = fakeWeb.Lists[""].Items.Add();

Isolate.WhenCalled(() => fakeItem[0]).WillReturn(1);

Registration registration = new Registration(){
RegistrationStatus = "Pending",
UserId = 100

RegistrationRepository repository = new RegistrationRepository();
int id = repository.Add(registration, false, fakeWeb);

Assert.AreEqual(1, id);
Isolate.Verify.WasCalledWithExactArguments(()=> fakeItem[Fields.Title] = "UnitTest");
Isolate.Verify.WasCalledWithExactArguments(()=> fakeItem[Fields.UserId]= 100);
Isolate.Verify.WasCalledWithExactArguments(()=> fakeItem[Fields.User]= fakeUser);
Isolate.Verify.WasCalledWithExactArguments(()=> fakeItem[Fields.Status]= "Pending");

First, you can see that it’s much shorter. The secret sauce is using the Members.ReturnRecursiveFakes option. This is very useful in the case of SharePoint or any hierarchical code model.

Another thing to notice, that once we use this recursive construct, we can now extract from the hierarchy the objects (fakeUser and fakeItem) we need for setting behavior and verification. Although, we could use the same chain inside the verification and behavior clauses if we want to. This is contrast to creating the mocks explicitly, then setting them as return values.

I like the power I get from using the recursive options. The tests are shorter and are more readable.

A note of warning: I’m running this with a build that will be out very shortly. We’ve stabilized the existing features in version 5.0, so you’ll be able to use this method from the upcoming release forward with more certainty. The next version is coming very, very soon.

Note that you can click the link to learn more on using SharePoint or to learn how to unit test a SharePoint application.

Technorati Tags:

Microsoft , Microsoft sharepoint , Unit Testing SharePoint, mock, Software Testing

  • iPhone software development

    Nice illustration using coding example… thanks…