Unit Testing with Windows Server AppFabric Caching
I like to do TDD whenever I can. So today I was writing some code that would be using the distributed cache features of Windows Server AppFabric and I decided to write unit tests first and then implement my code.
Writing code that uses an external store like a file, a database or a distributed cache is a challenge because you have to get the external store to a known starting point (or mock the external store).
I decided initially to try and just work with the DataCache. The question is how do I insure that the cache is clear when the test starts. I wish that there was a DataCache.RemoveAll(string cache) method – that would absolutely solve this problem but… there isn’t.
Option #1 – Create/Delete a named cache
My first try was to create a named cache, run the tests and then delete the cache. It worked great the first time, but the second time I ran the test it failed with an exception. Apparently it takes a long time for AppFabric Caching to delete a cache and it was still not done deleting it. This will never work…
Option #2 – Start / Stop Cache Cluster
What if I start/stop the cache-cluster? Seemed like a good idea but then I found out that after you invoke the Start-CacheCluster cmdlet, you need to wait about 10 seconds before trying to get a cache from the DataCacheFactory. Works but who wants to wait 10+ seconds before your first test can even run?
Option #3 – Remove Keys
The thing that finally worked but is my least favorite option is to simply remove they keys I’m using in tests. This works even if the key does not exist, it just means that I have to remember to add code to my ClassInitialize method to remove the keys whenever I add new code that will be using a key a didn’t use before.
And – if my code uses other code that generates keys from data then it’s going to get really complicated.
Option #4 – Mock DataCache
I have not tried this yet but this may be where I ultimately end up. This will allow me to get the exact behavior I want. Except that the API requires me to return things like a DataCacheItemVersion and DataCacheLockHandle which have no public constructors.
Creating a “Mockable” API requires that you provide interfaces like IDataCacheItemVersion or Abstract base classes and this API isn’t mockable in it’s current form.
Next Step
So today I’m going with Option #3 for now. It works but I have to remember to start up the cache cluster before running my tests. I’ll see how far I can get with this and maybe later try mocking the DataCache.
Comments
Anonymous
April 30, 2010
I haven't tested this but... Can't you have #5 where you create the cache with a random name that is bound to the test run then on tear down delete it (AppFabric will get round to it eventually!).Anonymous
May 06, 2010
Apparently TypeMock can mock out anything, even classes that aren't abstract nor follow an interface. Haven't tried it though. Maybe look into if this rumor is true :)Anonymous
May 06, 2010
Yes - TypeMock can do this. But I need to do this without TypeMock and show the team what it takes to get this done.