Unit Testing SharePoint with TypeMock (Part I)

Unit Testing SharePoint with TypeMock (Part I)
March 17 17:00 2011 Print This Article

As a developer testing isn’t necessarily fun but it is an essential aspect of what we do. I find it’s always a challenge to find the best approach that balances both the degree of coverage that makes the testing worthwild but doesn’t take 10 times longer to do than the original development did. I’ve seen some test plans for projects I’ve worked on that have amassed hundreds and hundreds of individual test steps which take a while to run through even with some degree of automation. Let’s not forget as well that with every new piece of development and release that the number of test scripts keeps on growing!

The question is, how much testing should be done (as a developer)…actually probably a better question is realistically how much testing should be done? There’s also a question as to how we test SharePoint sites? How can we reliable test a site when there’s a dependency on SharePoint itself, not to mention things like data is changing – a page that was there yesterday might not be there today etc? At work we’ve got testers who do a great job in preparing test scripts and do a lot with automation with tools like Selenium but testing still takes a while. We’ve seen it a number of times where the tests have been delayed because the data needed recreating because users had been deleted, or content changed!

Ideally we need a mechanism that allows us to test unit test code without a dependency on what data may or may not have been created. Also in context of my own testing that having to repeat something time and time again is frustrating – especially when I “know it works”. I need something (and I’m not alone in this) that can be easily be repeated and without too much manual interaction.

In trying to answer this I’ve been playing with TypeMock Isolator to try and introduce some unit testing within a SharePoint project and my custom code. TypeMock works by allowing us to minic SharePoint in code but without actually having SharePoint running. Since there is no SharePoint instance the “data” we supplied to the test scripts won’t change.

Even better, once a script is written barring any changes to functionality that script can be ran time and time again which makes things a lot easier! I’ve not delved into TypeMock in a great deal of detail – I’m sure there’s lots more to see, but I have to say that so far I’m impressed. Once you get you’re head round mocking (if you’re new to it like I was!) then it’s fairly easy to pick up.

An Example

I thought it might be interesting to share a proof of concept project I put together to provide a simple demo of what could be achieved. In this scenario I want to have a series of objects to represent documents in a document library. There are two objects:

  • MyDocument – represents a single document (DocumentTitle, Created, Created By, Modified and Modified By)
  • MyDocuments – represents a collection of MyDocument objects and has a series of methods to retrieve them

For this first method in MyDocuments is GetAll which as the name suggests gets all the documents from a document library, the code reads as follows:

   1:  SPWeb thisWeb = SPContext.Current.Site.RootWeb;
   2:  SPList documentList = thisWeb.Lists.TryGetList("Shared Documents");
   3:  if (documentList != null)
   4:  {
   5:      MyDocuments tempResults = new MyDocuments();
   6:      SPQuery query = new SPQuery
   7:      {
   8:          Query = "<Where/>"
   9:      };
  10:      var results = documentList.GetItems(query);
  11:      foreach(SPListItem item in results)
  12:      {
  13:          MyDocument myDoc = new MyDocument
  14:          {
  15:              DocumentTitle = item["Title"].ToString(),
  16:              CreatedBy =item["Created By"].ToString(),
  17:              ModifiedBy = item["Modified By"].ToString(),
  18:              Created = Convert.ToDateTime(item["Created"]),
  19:              Modified = Convert.ToDateTime(item["Modified"])
  20:          };
  21:          tempResults.Add(myDoc);
  22:      }
  23:  }

(Now before you comment there are deliberate mistakes (like not checking for nulls) that I’m going to use in the next post to highlight how these unit tests can aid development)

The first thing we need to do is to start working our way through this method to see what objects have a dependency on SharePoint and so we need to use TypeMock to mock (or fake) an object. So for example, the first line makes reference to SPContext.Current.Site.RootWeb which is where we’ll start. What do we expect this line to do? Well it should return the root web which is just an SPWeb object. TypeMock allows us to create fake objects, such as our SPWeb object and replace it wherever a call is made in code and here’s how:

   1:  var fakeWeb = Isolate.Fake.Instance<SPWeb>(Members.ReturnRecursiveFakes);
   2:  Isolate.WhenCalled(() => SPContext.Current.Site.RootWeb).WillReturn(fakeWeb);

The first line creates a fake SPWeb object for us, and the second line basically says “when you see a call to SPContext.Current.Site.RootWeb, return our fakeWeb object instead”. Rather than working through each line, let’s take a look at the complete method:

   1:  var fakeWeb = Isolate.Fake.Instance<SPWeb>(Members.ReturnRecursiveFakes);
   2:  Isolate.WhenCalled(() => SPContext.Current.Site.RootWeb).WillReturn(fakeWeb);
   4:  var fakeList = fakeWeb.Lists.TryGetList(MyDocuments.LIST_NAME);
   5:  Isolate.Swap.NextInstance<SPList>().With(fakeList);
   7:  var fakeQuery = Isolate.Fake.Instance<SPQuery>(Members.ReturnRecursiveFakes);
   9:  var fakeItem1 = fakeList.AddItem();
  10:  fakeItem1["Title"] = "document 1";
  11:  fakeItem1["Created"] = DateTime.Now;
  12:  fakeItem1["Modified"] = DateTime.Now;
  13:  fakeItem1["Created By"] = "User 1";
  14:  fakeItem1["Modified By"] = "User 1";
  16:  Isolate.WhenCalled(() => fakeList.GetItems(fakeQuery)).WillReturnCollectionValuesOf(new[] { fakeItem1 });
  18:  MyDocuments myDocs = new MyDocuments();
  19:  myDocs.GetAll();
  21:  Assert.AreEqual(1, myDocs.Count);
  22:  Assert.AreEqual("document 1", myDocs[0].DocumentTitle);

If you read through this test method what you see is that when we expect a “real” SharePoint object to be referenced we replace it with a fake object instead. In this way we can build up our fake objects as we need them and then we can call our original MyDocuments object and it’s GetAll method. Since the test is being run TypeMock is able to intercept any calls to the “real” SharePoint objects and replaces them with the fakes – even down to the point of the SPQuery that is run.

To finish off the test script there’s a couple of Assert statements so that we can ensure the correct information is being returned. We can run this test throughout development and can even get it included automatically as part of an automated build (TypeMock has a build server license). For me knowing that when code gets released to our testing environments that it has successfully passed the unit tests it should help elimate a lot of problems and hopefully mean testers find a lot less functional issues!

I’m still doing some digging around TypeMock so I’ll be adding a few more examples over the next few weeks so keep an eye out.

Source: http://blog.typemock.com

Related Posts:

  • No Related Posts

About Article Author

view more articles
Nataliia Vasylyna

View More Articles