Tag Archives: UnitTest

Detouring a constructor with Microsoft Fakes #dev #coding #tdd

I wanted to ensure every SmtpClient instance that was created by a library was also disposed of, to do this I first needed to Shim SmtpClient using Microsoft Fakes:

  1. Add Fakes Assembly for System.
  2. Edit Fakes/System.fakes
    Add

    <ShimGeneration>
      <Add TypeName="SmtpClient"/>
    </ShimGeneration>
  3. Save the file and close
  4. Rebuild, open the System.4.0.0.0.Fakes reference and under System.Net.Mail.Fakes you should see ShimSmtpClient.

My idea was to count up every time the constructor was called and to count down every time one was disposed, to do this I created a counter:

int instancesNotDispose = 0;

Incremented it in the Constructor Shim, that is wrap the constructor and do some more things rather than completely detouring the constructor:

ShimSmtpClient.Constructor =
    x =>
    {
        // Execute outside of Shims otherwise you'll be in StackOverflowException territory
        ShimsContext.ExecuteWithoutShims(
        () =>
        {
            // Use reflection to get the default constructor and invoke it, the magic here is the instance is stashed into x!
            var constructor = typeof(SmtpClient).GetConstructor(new Type[0]);
            constructor.Invoke(x, new Object[0]);
        });

        instancesNotDispose++;
    };

Then decremented it in the Dispose Shim:

ShimSmtpClient.AllInstances.Dispose =
    x =>
    {
        // Execute outside of Shims otherwise you'll be in StackOverflowException territory
        ShimsContext.ExecuteWithoutShims(x.Dispose);

        instancesNotDispose--;
    };

Then I can call my library a bunch of times to do whatever it does and sends some e-mails, then I can assert they have all be disposed:

Assert.AreEqual<int>(0, instancesNotDispose, String.Format("Doh! {0} were not disposed", instancesNotDispose));

Assuming there aren’t other SmtpClient constructors that do not call the default constructor then this code should work fine, if there are other constructors called that do not call the default constructor then this Assert will also help find those. There are other ways, for example, stashing each instance in a List and ensuring each is in both the Constructor List and the Dispose List, but this counting approach was enough for my needs for now.

Unit Test Projects and NUnit compatibility

I often need to write Unit Tests and have them accessible from NUnit as well as the Visual Studio Test View (etc), so I thought I’d write myself a walkthrough of the common things I have to do.

Firstly, whichever language I’m using, Visual Studio is normally configured to create the wrong one, so let’s say I’ve got my C# hat on and I create a test project:

Darn it, it’s created a VB.NET one, so I delete it and search for the setting or way I create a C# one. This can be located under Tools -> Options -> Test Tools -> Test Project, then choose your preference from the “Default test project language” dropdown, like so:

You will also notice you can choose what (if any) template test classes are created for you. 99% of the time I use Unit Test and that is it.
So you go back in and create the project again and it’s created a C# one, it automatically adds a reference to the Visual Studio Test classes, great:

Add a reference to NUnit, so you have:

Now let’s look at the Unit Test class, I’ve stripped it down to the bare bones:

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
}

Since we don’t want the Visual Studio and the NUnit classes to conflict my approach is to take out the Visual Studio using statement like so:

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;

namespace TestProject1
{
    [Microsoft.VisualStudio.TestTools.UnitTesting.TestClass]
    public class UnitTest1
    {
        [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]
        public void TestMethod1()
        {
        }
    }
}

Now this will still work as before, but we can add NUnit in now too, like so:

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;

namespace TestProject1
{
    [Microsoft.VisualStudio.TestTools.UnitTesting.TestClass]
    [TestFixture]
    public class UnitTest1
    {
        [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]
        [Test]
        public void TestMethod1()
        {
        }
    }
}

And proof of the pudding, Visual Studio:

NUnit:

This also reminds me, while I’m on the subject, to be able to open a Visual Studio project from within NUnit there is a setting you need to change, go to Tools -> Settings -> IDE Support -> Visual Studio and then tick the “Enable Visual Studio Support” checkbox, like so: