Unit testing MOSS part 1 (of 2)

Some of our team members, including me and Frank Jusnes, were recently responsible for providing recommendations on how to unit test in SharePoint projects, and this is an overview of our findings and experiences. This is the first of two posts on the subject giving an overview. In the second post we are aiming for more examples and explanations.

 

Background

 

Unit testing SharePoint has never been an easy task to accomplish due to the many dependencies on the SharePoint platform.

The only real alternative to unit testing SharePoint is by using isolating the unit tests from the outside world (also called Integration tests) with the use of Mock objects.

With the evolvement of .Net, there are now great easy-to-use tools (like the commercial Typemock) on the market one can use to create unit tests with techniques like lambda expressions and others.

 

In addition, the Microsoft Patterns and practices team has now released a guidance on SharePoint development which includes guidance on how to unit test in a SharePoint development projects.

 

The guidance recommends unit testing SharePoint using Mocks. The concept is that you have to isolate all the dependencies on SharePoint (and other external dependencies) with fake objects, and act on these fake objects instead.

 

With the Typmock Isolator tools we are able to isolate SharePoint out of the equation in our tests since it is possible to call into private methods, sealed classes and event handlers among others.

 

What tests to write?

The ambition level of test coverage is a difficult discussion to have, as there are many meanings on the subject, but here is what we initially suggest:

  • Positive tests verifying the flow of the code in successful calls
  • Input validation, all combinations
  • The logic of the code
  • And last but not least the Exception handling-flow

Terminology

Here are some of the more important terms used in relations to unit testing with the Typemock Isolator

  • Mock = Pretender object, intercepts the real object
  • Fake = Mostly the same as a Mock, but a simpler variant
  • Stub = Fake method call
  • Expectations = Prepare expected results for later Asserts

 

Way it works

 

Authoring unit tests with Typemock Isolator involves following a certain pattern when writing the test. This pattern is called:

Arrange-Act-Assert test authoring pattern

As the title implies, there are three sections you have to create in your tests.

  • Arrange: This is the section where you set up fake objects and expectations
  • Act: Here you perform the calls on your class in test (often faked objects calls)
  • Assert: In the end there has to be some verification and asserts

The Typemock framework has 3 API's you can use to create tests

 

Reflective mocks
1. generation API, do not provide strongly typed mock objects

 

Natural Mocks
2. generation API, uses a "recorder" to to set up expectations. Strongly typed mock objects

 

AAA Typemock Isolator
3. generation API. Strongly typed fake objects, more readable test code and can even fake live objects.
This is the API recommended to use for SharePoint unit tests, due to the fact that we are able to implicitly create hierarchies of fake objects. Especially valuable when it comes to faking e.g. SPSite objects.

That said, since the AAA Typemock API does not support all test scenarios one will probably have to combine at least AAA Typemock Isolator and Natural Mocks to get the full range of advanced test cases covered.

 

The following is a comparison between AAA, Natural Mocks™ and Reflective Mocks (from the Typemock site):

Feature

AAA

Reflective Mocks

Natural Mocks™
Compile time checks Yes No (methods are passed as strings) Yes
Refactoring support Yes Partial (methods are passed as strings) Yes
Fake recursive objects Yes No No
Call verification Yes Yes Yes
Static method behavior setting and verification Yes Yes Yes
Non-public methods mocking Yes Yes No
Argument checking Yes Fake chains Yes
Setting calls to behave as implemented Yes Yes Yes
Custom argument checking Partial (For non-public members only) Yes Yes
Conditional execution of custom code No Yes Yes
Repeating expectations No Yes Yes
Faking all instances No Yes Yes
Conditional expectations No Yes No

Some useful techniques in your test code

Creating Fakes that returns a provides full hierarchy recursively:

var fakeSite = Isolate.Fake.Instance<SPSite>(Members.ReturnRecursiveFakes);

Swap an instance of the live object with the Fake
Isolate.Swap.NextInstance<SPSite>().With(fakeSite);

 

Setting behaviour using .Whencalled and .WillReturn

Isolate.WhenCalled(() => fakeObject.Name).WillReturn("Name to return when called");

 

Setting behavior using .Ignore which will ignore the call (only on void methods)

Isolate.WhenCalled(() => fakeObject.VoidCall()).IgnoreCall();

 

Setting behavior using .WillReturn to tell what a call should return (only on methods returning values)

Isolate.WhenCalled(() => fakeObject.IntCall()).WillReturn(1); 

 

Verify behavior using .Verify. For instance if a method was called or not

Isolate.Verify.WasNotCalled(() => fakeObject.Update("This should not be called"));

 

 

How to attack?

First of all, if unit testing is a new technique to you, try get the overview by reading the excellent developer guide on the Typemock site. They also have videos providing intro to the framework. Get your head around the examples and try them out.

 

Use TDD principles to write good thought-through code, but if you have to create tests on some legacy code here are some tips:

 

First identify needed Fakes you will have to create
For instance if there is a SharePoint object creation in the code you test (e.g. SPSite):
- Create a Fake SPSite
- Replace the SharePoint object with the Fake (future swapped)

 

A SharePoint object method call following the previous instance (e.g. SPSite.OpenWeb):
- Replace it with a method call on the Fake SharePoint object

 

A SharePoint property get:
Replace it with a .WhenCalled/.WillReturn behavior setup on the Fake

 

Verify and Assert

 

Good luck!