WPF and MSTest

This post demonstrates a solution for overcoming the exception that is thrown when trying to test a WPF class with MSTest.

Problem

I was recently trying to run a unit test containing a WPF class and received the following error during test execution: "System.InvalidOperationException: 'The calling thread must be STA, because many UI components require this.'" This exception was thrown when I tried to instantiate a class that was derived from System.Windows.Controls.UserControl. It's complaining because only STA threads can create those types of classes and my unit test isn't an STA thread.

I did some Googling and just about every result that appeared was for NUnit, but I'm using MSTest (MSTest.TestFramework), so I needed a solution for that framework specifically.

Solution

The solution was actually really simple when I found this link. I created a WpfTestMethodAttribute class and then applied it to my unit tests.

Here's the WpfTestMethodAttribute. It is used instead of the normal TestMethodAttribute that MSTest provides.

public class WpfTestMethodAttribute : TestMethodAttribute
{
    public override TestResult[] Execute(ITestMethod testMethod)
    {
        if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
            return Invoke(testMethod);

        TestResult[] result = null;
        var thread = new Thread(() => result = Invoke(testMethod));
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        thread.Join();
        return result;
    }

    private TestResult[] Invoke(ITestMethod testMethod)
    {
        return new[] { testMethod.Invoke(null) };
    }
}

Here's a quick and dirty example of the attribute in use.

[TestClass]
public class MyTestClass
{
    [WpfTestMethod]
    public void MyWpfTest()
    {
        // The following line will fail unless executed on an STA thread.
        var userControl = new UserControl();
        Assert.IsNotNull(userControl);
    }
}