SharePoint Unit Testing withTypeMock (Part 4)

The SharePoint Baker has previously wrote about unit testing for SharePoint. See his previous posts (1,2,3) and what others have written about unit testing in SharePoint. This post is reprinted with permission. If you want to write a guest post for the Typemock blog, please email avi@typemock.com.

Here’s the latest installment on my TypeMock series about unit testing with SharePoint. What for me started as purely an interesting proof of concept has grown to the point where we’re at the early stages of adopting TypeMock for providing some degree of unit testing around our SharePoint code. Being able to compliment our existing system and regression testing (which has been focused on manual, front-end testing) is make a big difference. Since I’ve been spear heading this, I know as soon as other developers start picking this up I’m going to get a lot of “how to you do this….?” questions. I figured those answers would make a good blog post and hopefully help others as well who are getting started. I figured I’d start by looking at some broad testing approaches and how we can test different types of methods within our code. Over the next few posts I’ll hopefully look at other areas of testing so there can be a kind of reference point of “how to”.

How to test Methods

Since unit testing in general focuses on testing small units of code, testing methods is a good place to start. I’m just going to take a look at a few different types of methods and show how we can use TypeMock to test them. The approaches I’ve taken here are not necessarily the only ones but they used in real world test scripts that we’ve used internally so I know they work.

Public methods

Here’s our first example, a public method. It doesn’t do anything particularly existing, it just returns the title of the current SharePoint web object.

   1: public string GetWebTitle()

   2: {

   3:     return SPContext.Current.Web.Title;

   4: }

So for our unit test we need to use TypeMock to produce a fake version of the SPContext and return a Title. In order to keep the code simple I’m just going to use the WhenCalled method that is available:

 

   1: [TestMethod]

   2: public void GetWebTitle()

   3: {

   4:     Isolate.WhenCalled(() => SPContext.Current.Web.Title).WillReturn("TestWeb");

   5:     var example = new Example4();

   6:     Assert.AreEqual("TestWeb", example.GetWebTitle());

   7: }

As you can see from the test method, testing public methods is really easily. Simply setup your fake objects to return the information expected for the test – so this case we’re only overriding SPContext.Current.Web.Title. If our code was a bit more detailed and used other objects like SPSite, SPList, SPQuery etc then we would need to do a lot more here like setting up fake objects etc. Once we’re got our setup, it’s then just a case of creating the object and calling the method we want to test. Of course let’s not forget to include some Assert statements so that we can actually check we’ve got the result we were expecting.

Public Static Methods

Let’s take a look at static methods. This this case the method does exactly the same as before, the only difference is our method is static.

   1: public static string GetStaticWebTitle()

   2: {

   3:     return SPContext.Current.Web.Title;

   4: }

The test is arranged in pretty much identical to the public method, except in this case we can call the static method directly without having to first create an object.

   1: [TestMethod]

   2: public void GetStaticWebTitle()

   3: {

   4:     Isolate.Fake.StaticConstructor();

   5:     Isolate.WhenCalled(() => SPContext.Current.Web.Title).WillReturn("TestWeb");

   6:  

   7:     Assert.AreEqual("TestWeb", Example4.GetStaticWebTitle());

   8: }

Private methods

Here’s where things get a little more interesting. How can we test a private method? If we look at how the public method was tested it involved calling the method from within the test, but we can’t do that with private methods because they won’t be exposed in our test project. I’ve found two different approaches here for different situations – one which actually tests the method and another which fakes the method.

   1: private string GetPrivateWebTitle()

   2: {

   3:      return SPContext.Current.Web.Title;

   4: }

If we want to test a private method, like we test a public method, we have to take a slightly different approach. To start with, we still use TypeMock to setup our test data against SPContext but we don’t create our object for testing (how can we since the private method isn’t exposed?). Instead we have to use an option that is part of Visual Studio which creates an accessor for the private methods (and properties). You can read about it here on MSDN if you’d like more details. How we do is is by right clicking the private method in your code, one of the options should be for ‘Create Private Accessor’ with an option to your test project.

MSDN Unit Tests

What this does is it creates an .accessor file. What this allows us to do it to create a new object within our test scripts which exposes the private methods. So for this private method this is what the test looks like.

   1: [TestMethod]

   2: public void GetPrivateWebTitle()

   3: {

   4:    Isolate.WhenCalled(() => SPContext.Current.Web.Title).WillReturn("TestWeb");

   5:  

   6:     var fakeAccessor = new Example4_Accessor();

   7:     Assert.AreEqual("TestWeb", fakeAccessor.GetPrivateWebTitle());

   8: }

See how it uses the Example4_Accessor object, which we can use to test the private methods just like public methods. Apart from the object that is being created (Example4_Accessor rather than Example4) the way we setup the tests is pretty much the same. This is the first option I mentioned which allows us to test the inner workings of a private method. But with private methods it’s fairly safe to assume that it is being called from somewhere else in code- like another public method.

   1: public string GetWebTitleThroughPrivateMethod()

   2: {

   3:     var title = GetPrivateWebTitle();

   4:     return title;

   5: }

In this case, since we’re not really interested in what GetPrivateWebTitle does, we can assume that it works properly and we don’t need to test it as part of this method. So what we can do is use TypeMock to simply return a value instead, so during the test the GetPrivateWebTitle method doesn’t get called we simply get a value back.

   1: [TestMethod]

   2: public void GetWebTitleThroughPrivateMethod()

   3: {

   4:    var example = new Example4();

   5:    Isolate.NonPublic.WhenCalled(example, "GetPrivateWebTitle").WillReturn("TestWeb");

   6:    Assert.AreEqual("TestWeb", example.GetWebTitleThroughPrivateMethod());

   7: }

Of course there’s nothing stopping us from still mocking GetPrivateWebTitle as well and to achieve this we can use the CallOriginal method.

   1: [TestMethod]

   2: public void GetWebTitleThroughPrivateMethod_WithCall()

   3: {

   4:     Isolate.WhenCalled(() => SPContext.Current.Web.Title).WillReturn("TestWeb");

   5:  

   6:     var example = new Example4();

   7:     Isolate.NonPublic.WhenCalled(example, "GetPrivateWebTitle").CallOriginal();

   8:     Assert.AreEqual("TestWeb", example.GetWebTitleThroughPrivateMethod());

   9: }

Of course there’s nothing stopping us from still mocking GetPrivateWebTitle as well and to achieve this we can use the CallOriginal method.

   1: [TestMethod]

   2: public void GetWebTitleThroughPrivateMethod_WithCall()

   3: {

   4:     Isolate.WhenCalled(() => SPContext.Current.Web.Title).WillReturn("TestWeb");

   5:  

   6:     var example = new Example4();

   7:     Isolate.NonPublic.WhenCalled(example, "GetPrivateWebTitle").CallOriginal();

   8:     Assert.AreEqual("TestWeb", example.GetWebTitleThroughPrivateMethod());

   9: }

Here we arrange our data as we’ve done in previous examples and then we can re-use the same code as before. However instead of calling WillReturn with our test data we can call CallOriginal which as the name suggests runs the method. Since we’ve already setup our SPContext with TypeMock that gets returned and our test suceeds.

Summary

Well that’s a quick look at how we can test different methods and how we can control how much individual tests have to do. Since the benefit that TypeMock gives us is being able to test SharePoint objects I think that will be the next thing I look at – providing some examples on how to test different SP objects, so keep your eyes peeled!

TOP