How we decided to unit test the OfficeDevPnP core
Overview
Unit testing the Office Developer Patterns & Practices Core solution was definitely a challenge for us. Since it was grown from community code samples, most of the testing was done by refactoring similar code so it worked across many samples. The problem is that the Core component has become more and more reliable and the method signatures are not tested unless we run individual tests.
Fakes vs. Real Tenant
Mock objects, or Fakes as they're called in VS, are a great solution for unit testing. They allow us the ability to act as both the server and the client to abstract our tests from SharePoint. However, given that there isn't a fakes framework already developed for SharePoint, it's very difficult to implement all the scaffolding for SharePoint CSOM and be able to ensure that objects are properly initialized as expected. This led us to believe that the effort of building such a thing is less valued than testing the Core solution against a developer tenant.
Console Application?
The console application is the old faithful. Anyone can write a Console app to unit test code and write out all their assertions and exceptions. This tried and true method has been a great solution for C++ developers; however, given the number of options out there, this was obviously not feasible. We wanted build integration via TFS and we wanted the community to be able to easily extend the app, which wouldn't happen this way. Ironically, when quickly testing a change to the API I was actually testing via console app in an ignored path…do what you have to, you know?
Client ID/Secret?
Using OAuth to test against the developer tenant is a great approach and would definitely validate a connection and that your code functions. Given that the Core assembly assumes that what is being passed in is a valid ClientContext object and almost all methods use a server object, the assumption is that authorization has already been established. The complexity of configuring the app with a client id/secret with the SP server during testing, it doesn't exactly seem the right approach when the wish is to test that all unit tests are valid for tenant-level permissions.
Ah, SharePointOnlineCredentials!
In the end, the right solution for this was decided to be to use SharePointOnlineCredentials to initialize the ClientContext object. This means that we can supply an app.config file that has dev site and tenant URLs to properly along with username and password. To initialize a ClientContext, one can simply use the format:
var spCredentials = new SharePointOnlineCredentials(username, password);
using (var clientContext = new ClientContext(devSiteUrl)){
clientContext.Credentials = spCredentials;
// perform CSOM operations
}
Put My Password in App.Config?
Obviously, it's not a good practice to put your username/password in the App.config file, especially since this is shared code that is community driven and you don't want it to accidentally get pushed to your fork. So, we simply added the App.config file to .gitignore to leave it out leaving that responsibility to you. The App.config.sample file in the new OfficeDevPnP.Core.Tests project which can be copied in your local solution, renamed to app.config, filled in, and you can unit test. Check it out in the dev branch.
Cheers!
Comments
Anonymous
September 29, 2014
What about SharePoint Emulators? blogs.msdn.com/.../introducing-sharepoint-emulators.aspx channel9.msdn.com/.../3-015 Are there SharePoint Emulators for SP CSOM code?Anonymous
November 19, 2014
The point is, we want to go against the tenant because the tenant changes regularly. Something may work differently in the future and we won't know if we use mock objects.