Shim Saves The Day in A Tricky Unit Test Situation
Editor’s note: The following post was written by Visual C# MVP William Wegerson
This is a story that actually happened to me and it illustrates how I could have used Visual Studio 2012 testing framework of fakes and shims to overcome an insurmountable testing failure that transpired at that time.
It all happened on a contract that I took at a financial company. They had an existing system going all the way back to VB6 and were just now (then) sprinkling in WPF into their existing system. They were unit testing freaks and by God or Buddha there had to be a unit test for every piece of code owned and even some that they didn’t own. If the blanket of code coverage didn’t safely tuck in the crying assemblies at night with a nice pacifier the project lead would wrap my knuckles like mother superior over a biblical infraction on the school yard. In retrospect I am linked-in to him this day so this story doesn’t turn out half bad.
Ok you get the idea of the situation, they mocked the heck out of all the code with a nameless but powerful mocking tool. But of course my code which I had to mock had a twist in it that at the time as mentioned could not be worked out. The originating assembly which my code du jour depended on at one point would internally create a new instance of some unholy object.
Since this was a true object and not an interface it couldn’t be swapped out with a test mock due to its being buried deep, deep into the code which my code called. Of course the usage of the object had dire consequences that basically made any unit test untenable to the mocking framework.Yes I was being mocked and my knuckles were rapped by the lead anyway out of pure frustration and the code I was writing simply did not have a unit test for it.
If we would have had the Ultimate version of Visual Studio 2012 which has the fakes baked in, we could have worked around the instance creation by creating a shim. I will not get into a long example which mimicked what I saw, for you can make that leap of faith by looking at this simple code I have shimmed up.
Below are the steps needed to Shim up DateTime.Now which will represent an assembly which can’t be stubbed/mocked via an interface.
1. In your C# unit test project right click on the System reference and choose “Add Fakes Assembly”
2. Create a unit test and that unit test file add these usings:
3. Here is the Example unit test code:
[Description( "Unit test" )]
public virtual void TestShim()
ShimDateTime.NowGet = () => new DateTime( 2012, 1, 1 );
var fakeTime = DateTime.Now; // It is always midnight on Jan 1st 2012
The usingcreates a scope where all things contained are dictated by any shim we may specify. Meaning that if any other code happens to fall within that context and calls DateTime.Now that code will, by design or not, get the same date regardless of the number of times called.
The delegate passed into the NowGet of the ShimDateTime loads our fake friend of a time which will always return that specific datetime of January 1, 2012.
Finally we call the actual DateTime.Now which has been supplanted by our shim and always returns that date mentioned.
Summary: That way regardless of when we run this test it always returns the same date. In this example we directly call DateTime.Now, but if we had code that also called the method Now elsewhere not seen by the unit test, it would also receive the same answer.
If I could have used a Visual Studio 2012 shim, I could have created a fake object to be returned during my contract and avoided the knuckle bruising from the lead. This is a perfect example of when to use it, but if you can use stubs, those are better, but if you are in a jam…the shim is your non fake friend.
About the author
William Wegerson is a C# Architect and Developer who has been working in Denver CO USA for over 20 years. He enjoys interacting with the community by being the featured speaker at groups along the front range such as the Denver Visual Studio User Group on a wide range of topics, including Silverlight and also showing the new features of Visual Studio 2010 and two years later on VS 2012. William has been awarded Microsoft MVP status in C# since 2008, due to his community work from speaking engagements, his blog (OmegaCoder.Com), as well as his work on the MSDN forums and StackOverflow.