Invoking the Static Constructor via Reflection

17/06/2010

tags: , , ,
5 comments

— Warning! —
This post may cause the reader a slight feeling of nausea. However, remember that tough situations call for some tough actions!

The Situation

Imagine that you have to write some-unit tests for a class which uses an existing infrastructure, involving calls to static methods on a static class. To make things worse, this static class also holds some state which, unfortunately, gets carried around between tests without no actual ability to clear it.

    public static class MyInfrastructureClass
    {
        private static Dictionary<int, string> _someState =
new Dictionary<int, string>();
        private static List<double> _someOtherState = new List<double>();

        public static void SomeOperation1()
        {
            // ...
        }

        public static void SomeOperation2()
        {
            // ...
        }
    }

After a unit-test is run, the state of the above class is not fresh, and as a result unit-tests can influence each-other and their success is dependant on the order in which they are run. This is obviously a very bad situation to be in.

Possible Solution

If there is no inherent built-in way to clear the state of the static class, then one can think of two possible solutions:

  1. Add a “Reset()”-like static method especially for unit-tests which is responsible of reinitializing the class’ state. While this solution is feasible, it involves writing special code for unit-tests which has to be maintained, and if the static class’ code is not yours this is not possible in the first place.
  2. Dynamically invoke the static constructor via reflection – this is the solution I would like to demonstrate.

Invoking the Static Constructor

Not many people know this, but it is possible to invoke the static constructor via reflection, much like the way you dynamically invoke any other method.

    ConstructorInfo constructor = typeof (MyInfrastructureClass)
.GetConstructor(BindingFlags.Static | BindingFlags.NonPublic,
null, new Type[0], null);

    constructor.Invoke(null, null);

The above code can be placed at the initialization or teardown stage of each unit-test, resulting in a clean-up of the static class’ state. This looks nice, however when using this solution you should be very careful – dynamically invoking the static constructor breaks the CLR’s promise that the static constructor would be called exactly once. This might break up the class’ implementation if it does not expect it and should be thoroughly inspected. With the above being said and kept in mind, if the static constructor only initializes and clears up the class’ state this might be an easy solution for unit-testing when infrastructure code refactoring is not possible.

My Two Cents

Static classes are a possible .NET implementation for the Singleton Pattern. This implementation has it strengths, however in my opinion it should be avoided as much as possible. The reason for this is mainly Unit-Test unfriendliness – static classes encapsulate state which cannot be easily reinitialized and implementation which cannot be easily replaced with mocks using standard, open mocking libraries.

When required to implement the Singleton Pattern, I usually prefer using a singleton instance accessed via an interface. For example:

    public class MySingletonClass : IMySingletonClass
    {
        private static readonly MySingletonClass _instance =
new MySingletonClass();
       
        public static IMySingletonClass Instance
        {
            get { return _instance; }
        }

        private MySingletonClass()
        {
            // Singleton initialization
        }

        // IMySingletonClass implementation
        // ...
    }

This way clearing the state between unit-tests is very easy (just replace the singleton instance used), and replacing the implementation with a mock is also relatively easy but requires a degree of cooperation for the tested client class which should allow injecting the instance used from the outside.

Conclusion

I wouldn’t usually recommend dynamically invoking the static constructor, however the technique is sometimes useful for unit-tests and should be kept in your toolbox. Just remember – use it with caution!

In addition, when possible, try to avoid using static classes. Singleton instances are, in my opinion, a better way to go.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

5 comments

  1. Tomer Shamam30/06/2010 ב 22:27

    While it is not a good practice to use static-classes, you may use another two methods:

    1. The one and only – Reflection!
    2. Load test into new AppDomain, get results, then drop it.

    Reply
  2. Eran Stiller30/06/2010 ב 23:21

    @Tomer:
    I definitely agree about running each test in a fresh AppDomain and then dropping it, however bear in mind that it is much more complicated to accomplish using standard unit-test tools…

    Reply
  3. Sasha Goldshtein09/07/2010 ב 18:05

    It’s also much slower.

    Reply
  4. M22/07/2012 ב 11:59

    Or you could use RuntimeHelpers.RunClassConstructor() which guarantees it runs only once.

    Reply
  5. Eran Stiller22/07/2012 ב 12:13

    @M:
    The entire point is to invoke the static constructor again and again for each unit-test (i.e. more than once)…

    Reply