I expressed my frustration the other day on twitter when it comes to unit testing and code that reside in GAC (global assembly cache).
This problem may occur more often in frameworks that like to put their code in the GAC, like SharePoint for example.
Let’s examine this with an example:
Imagine the setup above.
A web part that has been provisioned as a farm solution, thus meaning that the assembly that holds that code is now in the GAC. Never mind if that is best practice or not…that is the case.
Now I want to refactor some of that code in the web part and use the concept of a view model that I want to put under test.
Let’s go to town adding that view model class and then add a test project with some test for the the view model.
The usual setup here is to add the test project and then use a project reference to the SharePoint project, that holds the system under test (which is my view model class).
Above is a very simple test (it is a demo…remember!!).
Let’s see what happens if I execute that test:
If you can’t see that, the error that you’ll get is a System.TypeLoadException. The reason for that is the assembly that the test will initialize is the one from the GAC which doesn’t yet have the view model class since I haven’t deployed it yet. You would get a similar but different exception even if that class was in the assembly in the GAC but if you add some new code to it that hasn’t been deployed yet.
I don’t want to have to deploy my wsp to SharePoint just to get the new code into the GAC. And secondly, i really don’t want to do that before each test run. What to do??
A friend of mine, Hugo Häggmark, offered the solution to simply put the system under test in the test assembly until it was finished and then move it into the appropriate/real assembly (or VS project). I took that suggestion and though about it a little more and came up with an alternative solution (or workaround) that I´d like to present here.
The Solution (or workaround)
Turns out the easiest thing to do is to use a feature called a linked file. Let me show you what I mean.
Instead of adding a project reference to the SharePoint project (that holds the view model which is my system under test) I just include that file as a link into my test project (add existing item and so on…).
The end result is seen above.
The upside to this is that any changes you make to that file is reflected in the “actual” file in the SharePoint project…it’s just a linked file.
The downside is that you may end up with many of the these files since your system under test will probably have dependencies on other files as well. The best use for this may be for new code that you have control over and such. For instance, use the concept of view model to break out complicated view logic into its own class thus relieving the code behind of an .aspx or .ascx file from doing more than it should (the s in solid etc). If you do that, you may have control over the dependencies of the view model and thus limiting the number of linked files you have to include. With that little side track over, let’s continue.
Turns out that when I now execute the test the end result is a bit different:
Now it tells me the “real” error, that it expected Hello to return world and it actually returned an empty string.
Red-Green-Refactor and when you’re done you can safely deploy to the GAC.