Microsoft SharePoint is a browser based web platform where you can set up Web sites
to share and manage information and documents and publish reports in order to make it easier for people
to work together.
Unit testing in Microsoft SharePoint faces several problems that Telerik JustMock
overcomes:
- Interfaces are rarely used - most objects in Microsoft SharePoint don't
implement public interfaces.
- Sealed classes - many Microsoft SharePoint elements are sealed.
- Internal constructors - many Microsoft SharePoint elements have internal
constructors. Even if there is no behavior that we need to mock, we still need to create an
instance of it.
In this topic we will cover some scenarios in unit testing Microsoft SharePoint.
Disallow SPContext.Current
Disallow calling SPContext.Current property.
| C# | Copy |
|---|
[TestMethod]
[ExpectedException(typeof(ApplicationException))]
public void ShouldThrowApplicationExceptionOnCurrent()
{
Mock.Arrange(() => SPContext.Current).Throws(new ApplicationException("Not allowed to call SPContext.Current"));
SPContext currentContext = SPContext.Current;
}
|
In this example we mock the static SPContext class. We arrange the Current property to
throw an ApplicationException once it is called. The constructor will initialize
the Message property of the exception using the "Not allowed to call SPContext.Current" string.
Mocking SPContext.Current
Arranging SPContext.Current property to return mock fake object.
| C# | Copy |
|---|
var fakeContext = Mock.Create<SPContext>();
Mock.Arrange(() => SPContext.Current).Returns(fakeContext);
SPContext currentContext = SPContext.Current;
Assert.IsNotNull(currentContext, "The current SPContext should not be null");
|
Here we arrange the Current property get to return fake object when called. After acting with
SPContext currentContext = SPContext.Current we verify that our fake object was actually returned
initializing the Current property. If the assertion fails we specify that
"The current SPContext should not be null" will be dispalyed.
Mocking SPContext.Current.Site
In this example we will mock the Site property get of the SPContext.Current object. We will use
the following class:
| C# | Copy |
|---|
public class Site
{
public static string GetHomePageUrl()
{
return SPContext.Current.Site.Url;
}
}
|
Follows the actual test code:
| C# | Copy |
|---|
var fakeSiteUrl = "http://www.telerik.com";
var fakeSharepointSite = Mock.Create<SPSite>();
Mock.Arrange(() => SPContext.Current.Site).Returns(fakeSharepointSite);
Mock.Arrange(() => fakeSharepointSite.Url).Returns(fakeSiteUrl);
string actualUrl = Site.GetHomePageUrl();
Assert.AreEqual(fakeSiteUrl, actualUrl);
|
We arrange that once the Url property of the static SPContext.Current.Site is called,
"http://www.telerik.com" is returned as a result. We act by calling the GetHomePageUrl method
in our sample class. It returns the ulr of the current site and thus "http://www.telerik.com".
Finally, this behavior is verified.
Mocking AllowAnonymousAccess Property
In the next two examples we mock the AllowAnonymousAccess property of
SPContext.Web and SPContext.Current.Web objects.
Firstly, let's mock SPContext.Web:
| C# | Copy |
|---|
var fakeContext = Mock.Create<SPContext>();
Mock.Arrange(() =>fakeContext.Web.AllowAnonymousAccess).Returns(true);
Assert.IsTrue(fakeContext.Web.AllowAnonymousAccess, "Our SPWeb should allow anonymous access");
|
Here we create fake instance of SPContext and then arrange the
AllowAnonymousAccess property to return true.
Now, let's mock SPContext.Current.Web:
| C# | Copy |
|---|
var fakeContext = Mock.Create<SPContext>();
Mock.Arrange(() => SPContext.Current).Returns(fakeContext);
var fakeWeb = Mock.Create<SPWeb>();
Mock.Arrange(() => fakeContext.Web).Returns(fakeWeb);
Mock.Arrange(() => fakeWeb.AllowAnonymousAccess).Returns(true);
Assert.IsTrue(SPContext.Current.Web.AllowAnonymousAccess, "Anonymous access should be allowed on our current SPWeb");
|
We create a fake instance of SPContext and pass it to the SPContext.Current property.
Then a fake instance of SPWeb is created that is arranged to be returned as a result once
its Web property get is called. Then, as in the previous example, AllowAnonymousAccess
is arranged to return true. Finally, we verify.
In both examples, if the assertion fails, a message is displayed.
Mocking SPList Class
Follows a slightly more complicated example. Here we mock SPList.
| C# | Copy |
|---|
var spWeb = Mock.Create<SPWeb>();
var spList = Mock.Create<SPList>();
var spListCollection = Mock.Create<SPListCollection>();
var spListItemCollection = Mock.Create<SPListItemCollection>();
Mock.Arrange(() => spWeb.Lists).Returns(spListCollection);
Mock.Arrange(() => spListCollection[Arg.AnyString]).Returns(spList);
Mock.Arrange(() => spList.GetItems(Arg.IsAny<SPQuery>())).Returns(spListItemCollection);
Assert.AreEqual(spListCollection, spWeb.Lists);
Assert.AreEqual(spList, spWeb.Lists["myList"]);
Assert.AreEqual(spListItemCollection, spWeb.Lists["myList"].GetItems(new SPQuery()));
|
This is what we do:
- Create a fake instance of SPWeb
- Create a fake instance of SPList
- Create a fake instance of SPListCollection
- Create a fake instance of SPListItemCollection
- Mock the fake instance of SPWeb from step 1. to return the fake instance of
SPListCollection from step 3. once the List property get is called.
- Next, arrange that a call to any index in the fake object of SPListCollection
returned in the previous step should result in the fake object of SPList from step 2.
- Finally in our arrangement, specify that getting any item from our SPList from the
previous step should result in the fake object of SPListItemCollection from step 4.
- Act/Assert. The last thing to do in this example is to verify that every call
will result in the proper fake object as specified above:
- spWeb.Lists will result in spListCollection
- spWeb.Lists accessed by any string index will result in spList
- getting any item from any SPList will result in spListItemCollection
To further understand the example consider the following class hierarchy:
- SPWeb.List returns SPListCollection
- SPListCollection["myList"] returns SPList
- SPList.GetItems(new SPQuery()) returns SPListItemCollection
See Also