Beginners Guide To Threading, CodeProject, Lambdas / Anonomous delegates, WPF

NUnit STA Threads & Testing WPF

During the course of the WPF project we are working on at work, we decided to go down the Agile/XP/TDD/Mocks/Continuous Integration route, which means Unit tests, lots of them.

We are using NUnit, which I really like, but we are also using WPF, we are obviously using the latest/greatest patterns AKA MVVM, but from time tom time it is nice to be able to test certain things on WPF controls/windows etc etc.

So I set out to create a small NUnit test like the following:


/* Style Definitions */ table.MsoNormalTable {mso-style-name:”Table Normal”; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:””; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:11.0pt; font-family:”Calibri”,”sans-serif”; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:”Times New Roman”; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:”Times New Roman”; mso-bidi-theme-font:minor-bidi;}

diag11.jpg
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Now to me this looked fine, but when I ran this code I got the following horror show.

STAThread

Where NUnit moaned about “The calling thread must be STA”. Oh, that’s to bad. So I had a small think, and then came up with this small idea, just pass the original code to a helper class and have it run that in a Thread using STA threading apartment state. Sounds cool, but did it work. Well yes actually it did, and here is the small helper class.

 

 diag2.jpg


.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }And here is how to use this from a NUnit test.


/* Style Definitions */ table.MsoNormalTable {mso-style-name:”Table Normal”; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:””; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:11.0pt; font-family:”Calibri”,”sans-serif”; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:”Times New Roman”; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:”Times New Roman”; mso-bidi-theme-font:minor-bidi;}

diag3.jpg

And just to prove it works, here is a screen shot of the actual test running successfully.

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }STAThreadOK

Here is a link to a small test project that you can see this working with : wpfandnunittest1.zip in case you want to use this in your own projects.

Enjoy

20 thoughts on “NUnit STA Threads & Testing WPF

  1. Doh, I even left a comment on that article you wrote, must have forgot about that. Oh well proves we are both cool, I guess.

  2. there is problem with this, here is an example:
    add the following to class UserControl1
    private string foo;
    public String Foo
    {
    get
    {
    return “foo”;
    }
    set
    {
    foo = value;
    }
    }
    add the following test to class UserControlTests
    [Test]
    public void TestFoo()
    {
    ThreadExecutor.RunCodeAsSTA(
    delegate
    {
    WpfAndNUnitTest.UserControl1 uc1 = new WpfAndNUnitTest.UserControl1();
    uc1.Foo = “Set the property”;
    Assert.AreEqual(“Set the property”, uc1.Foo);
    });
    }

    the test should fail, but it succeeds.

    basically the RunCodeAsSTA must not only kicks off the new Thread, it should be wait for the thead to complete before return.

  3. Andrew, Having just read Provost’s site, you probably would want to store the Exception as he shows, or you could in my example log it, or re throw and catch that outside the STA codeblock call. I didn’t do that as I wanted to keep it a simple example, I figure people could throw and catch what they want.

    Oh well looks like there are lots of resources now, for people to choose from

  4. Wouldn’t it be easier to set the threading model to STA in the nunit config file.
    I also needed to do this when using WatiN for testing my web application.

    (example config:

    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    )

  5. Oops my < and > aren’t shown…
    1 <?xml version="1.0" encoding="utf-8" ?>
    2 <configuration>
    3 <configSections>
    4 <sectionGroup name="NUnit">
    5 <section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/>
    6 </sectionGroup>
    7 </configSections>
    8 <NUnit>
    9 <TestRunner>
    10 <!– Valid values are STA,MTA. Others ignored. –>
    11 <add key="ApartmentState" value="STA" />
    12 </TestRunner>
    13 </NUnit>
    14 </configuration>

  6. Oeps my < and > aren’t shown…

    1 <?xml version="1.0" encoding="utf-8" ?>
    2 <configuration>
    3 <configSections>
    4 <sectionGroup name="NUnit">
    5 <section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/>
    6 </sectionGroup>
    7 </configSections>
    8 <NUnit>
    9 <TestRunner>
    10 <!– Valid values are STA,MTA. Others ignored. –>
    11 <add key="ApartmentState" value="STA" />
    12 </TestRunner>
    13 </NUnit>
    14 </configuration>

  7. Sorry, sorry
    Apparently Mark Nijhof already mentoins this in his blog post!

    And Sorry Sasha for spamming your blog (it was unintentional) 🙂

Leave a reply to sacha Cancel reply