Below is the code. It is fairly well documented with an example and is included in Habanero.Base.
This is a modification of the code found here
"http://stackoverflow.com/questions/343521 /using-nunit-2-5-requiresstaattribute-with-teamcity-4"
/// /// This class is used when you specifically require some code method to run in MTA or STA thread. /// /// /// Unfortunately not all test runners implement the [RequireSTA] or other attributes such as config files. /// This may result in tests passing in NUnit GUI failing on the build server or failing on another developer's machine /// e.g. someone using Resharper. By using this Component you can ensure that the Individual test runs as required. /// The common requirement for STA threading is a visual component under test. /// /// /// ///[Test] ///public void Test_SetSolution_WithNull_ShouldRaiseError() ///{ /// CrossThreadRunner runner = new CrossThreadRunner(); /// runner.RunInSTA(delegate /// { /// //---------------Set up test pack----------------- /// ReportSourceDefCreatorControl creatorControl = new ReportSourceDefCreatorControl(); /// //---------------Assert Precondition------------- /// //---------------Execute Test--------------------- /// try /// { /// creatorControl.SetSolution(null); /// Assert.Fail("expected ArgumentNullException"); /// } /// //---------------Test Result-------------------- /// catch (ArgumentNullException ex) /// { /// StringAssert.Contains("Value cannot be null", ex.Message); /// StringAssert.Contains("solution", ex.ParamName); /// } ///}); ///} /// /// public class CrossThreadRunner { private Exception _lastException; /// /// Run the specified delegate in the MTA Thread. /// ///The delegate to be run in the MTA Thread public void RunInMTA(ThreadStart userDelegate) { Run(userDelegate, ApartmentState.MTA); } /// /// Run the specified funcion delegate in the MTA Thread and return the return value of the function. /// /// The function delegate to be run in the MTA Thread /// The return value of the function public TReturn RunInMTA(Function function) { TReturn returnValue = default(TReturn); RunInMTA(delegate { returnValue = function(); }); return returnValue; } /// /// Run the specified delegate in the STA Thread. /// ///The delegate to be run in the STA Thread public void RunInSTA(ThreadStart userDelegate) { Run(userDelegate, ApartmentState.STA); } /// /// Run the specified funcion delegate in the STA Thread and return the return value of the function. /// /// The function delegate to be run in the STA Thread /// The return value of the function public TReturn RunInSTA(Function function) { TReturn returnValue = default(TReturn); RunInSTA(delegate { returnValue = function(); }); return returnValue; } private void Run(ThreadStart userDelegate, ApartmentState apartmentState) { _lastException = null; Thread thread = new Thread(() => MultiThreadedWorker(userDelegate)); thread.SetApartmentState(apartmentState); thread.Start(); thread.Join(); if (ExceptionWasThrown()) ThrowExceptionPreservingStack(_lastException); } private void MultiThreadedWorker(ThreadStart userDelegate) { try { userDelegate.Invoke(); } catch (Exception e) { _lastException = e; } } private bool ExceptionWasThrown() { return _lastException != null; } [ReflectionPermission(SecurityAction.Demand)] private static void ThrowExceptionPreservingStack(Exception exception) { FieldInfo remoteStackTraceString = typeof(Exception).GetField( "_remoteStackTraceString", BindingFlags.Instance | BindingFlags.NonPublic); remoteStackTraceString.SetValue(exception, exception.StackTrace + Environment.NewLine); throw exception; } }
///[Test] ///public void Test_SetSolution_WithNull_ShouldRaiseError() ///{ /// CrossThreadRunner runner = new CrossThreadRunner(); /// runner.RunInSTA(delegate /// { /// //---------------Set up test pack----------------- /// ReportSourceDefCreatorControl creatorControl = new ReportSourceDefCreatorControl(); /// //---------------Assert Precondition------------- /// //---------------Execute Test--------------------- /// try /// { /// creatorControl.SetSolution(null); /// Assert.Fail("expected ArgumentNullException"); /// } /// //---------------Test Result-------------------- /// catch (ArgumentNullException ex) /// { /// StringAssert.Contains("Value cannot be null", ex.Message); /// StringAssert.Contains("solution", ex.ParamName); /// } ///}); ///} ///
This website is best viewed in Internet Explorer 7 & 8; Firefox 3.6.11; Opera 10.63; & Safari 4.