-
Using Fakes Framework to Streamline Unit Testing Woes
Posted on July 11th, 2013 No commentsI love having unit tests. However, sometimes there are… obstacles to generating the unit tests I want. Like any good unit tester, I want to be able to set up mock objects to help isolate the code I’m testing. Unfortunately most of the decent mock object frameworks rely heavily on dependency injection to get your mock object into the code you want to test.
Dependency injection is fine, but I hate refactoring a bunch of old code (that is stable, clean, and maintainable) just for the purpose of getting a unit test working. Well, that’s where Microsoft’s new Fakes Framework comes in.
The Fakes Framework provides two basic tools. Stubs are mock objects that work like most other mock objects you’ve dealt with. You give it an interface, it gives you a mock object that you can initialize for your unit test. Nothing too surprising there. However, the really interesting feature of the Fakes Framework comes in the form of Shims.
Shims allow you to circumvent any .NET method so that it returns what YOU tell it to. The classic example provided by Microsoft is the DateTime.Now property. Typically, this returns the current date and time. We all know that. However, I can use Shims to force it to return an arbitrary date and time, like Jan 1, 2000, for example.
1 2 3 4 5 6 7
// create a ShimsContext; cleans up shims using (ShimsContext.Create() // hook delegate to the shim method to redirect DateTime.Now // to return January 1st of 2000 ShimDateTime.NowGet = () => new DateTime(2000, 1, 1); Y2KChecker.Check(); }
Now, anytime Y2KChecker.Check() calls DateTime.Now it will receive Jan 1, 2000 instead of whatever the date is now. The implications for testing any kind of time-sensitive code is pretty clear. But how does this help with regular mocking? Couldn’t you just Shim everything and then be good to go?
Well, yes, I suppose you could, but the power of a good mock object framework is in reducing the amount of code you have to write, and helping you to not shoot yourself in the foot. Shims are flexible and powerful, but I’d still rather use a mock object framework that will provide useful features like verification.
But let’s say you have some Legacy CodeTM that relies on some kind of data access objects that you want to abstract out of your current unit test. After all, you don’t want to test the database access, you just want to test your code to make sure it’s processing the data correctly. The catch is that you aren’t using dependency injection so there isn’t really a clean way to get your mocked object into your code… oh but there is. Shims!