tags:

views:

59

answers:

2

Hi,

I have this CacheManager class which keeps a static dictionary with all sorts of cached data. However, with this dictionary being static it gets filled up with data from the other unit tests. This keeps me from unit testing whether or not the CacheManager is empty on init, and breaks with the principles of unit testing.

Any ideas how to create a proper unit test for this?

Code

public class CacheManager
{
   private static readonly Dictionary<ICacheKey, ListCacheItem> cacheEntries =
       new Dictionary<ICacheKey, ListCacheItem>();

   public static Dictionary<ICacheKey, ListCacheItem> CacheEntries
   {
       get
       {
           lock (cacheEntries)
           {
               return cacheEntries;
           }
       }
   }
+1  A: 

Generally, this is not a good idea from a testing perspective. By making the members of CacheManager static, you will never be able to isolate it in such a way to make it nice to unit test.

Perhaps a better solution is the Singleton Pattern. To do this, get rid of the static modifiers on CacheManager's members. Then you can have one static instance in your app that is used by everyone else. Therefore, in your unit test, you could create a new instance of the class that you can test in isolation, but still have the desired functionality.

David Y. Ross
How is this any better? Won't the singleton also keep the values between tests?
KoMet
Correct, the Singleton will. But you can instantitate the `CacheManager` itself and test its members in isolation. Then in other tests, for example, you can make sure all other parts of your app are using the same Singleton instance.
David Y. Ross
So actually your solution would be to create a new Singleton class which contains an instance of the CacheManager as one of its members?
KoMet
In CacheManager you can have a static method getInstance() that returns your Singleton instance.
David Y. Ross
The whole point of a singleton is to instantiate only one object, so I don't see how I could instantiate the CacheManager without affecting other unit tests. However you've given me a better idea (see previous comment), thanks for that.
KoMet
+1  A: 

Short answer: you can not do it properly. Unit testing and statics do not play really well together, you will (almost) always run into problems like the one you mentioned.

Longer answer: best solution would be to refactor your code. Even if you need the singleton behavior you have several options (e.g. dependency injection). David's recommendation is of course also an option that would at least let you test your cache, but you may still have problems when you want to test the rest of the system.

If for some reason you want to stick to your current design you can still have some (not necessary nice) workarounds. Some examples:

Easiest might be to add a "cleanCache" method. In some situations it might be even useful for the rest of the system, and each of your tests could also do it as the first step (in "setup/beforeTest or similar methods").

You could also play with visibility and let your tests do cleanup that is not allowed for the rest of the code.

These hacks will probably work as long as you do not run your tests in parallel.

Sandor Murakozi