Tuesday, October 11, 2011

Constructor vs. ClassInitialize

I recently ran across some code in a test class where I saw that the class was initialized in a constructor rather than in a method with the ClassInitialize method, and it made me wonder - what's the difference?

The goal is that we have a test class with several test methods, and we have some initialization code that is common to all of the test methods.  We want the initialization code to run only once for the entire set of tests, not once per test.

One way to do this is to put the initialization code in the constructor, like this:

        public MyTestClass()
        {
            var x = 5;
            x.Should().Be(4);  // Fluent Assertions
        }

Another way is to create a static method with the ClassInitialize attribute, like this:

        [ClassInitialize]
        public static void Init(TestContext testContext)
        {
            var x = 5;
            x.Should().Be(4);  // Fluent Assertions
        }

So what's the difference?


After asking Google, I found that some people mentioned that if done in the constructor, the code would be called once for each test, as the class would be instantiated once for each class.  This can be alleviated by having a static constructor, but the question remains - what's the difference between using a static constructor and using a static method with the ClassInitialize attribute?

After running some failing tests with the above initializers, I found a difference.  When using the constructor, if you have an assertion in the constructor that fails, as is the case n the first example above, you'll see a test failure message like this:

Class Initialization method MyTests.MyTestClass.Init threw exception. System.TypeInitializationException: System.TypeInitializationException: The type initializer for 'MyTests.MyTestClass' threw an exception. ---> Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Expected <4>, but found <5>..
Expected <4>, but found <5>.

However, if you use the ClassInitialize attribute, as seen in the second example above, you'll see this test failure message:

Expected <4>, but found <5>.

Which one do you think is quicker to digest?

No comments: