Get Your Window Ran
First thing first, you should get your window shown and ran. If your window is a child window of your whole application, then you have to create a fake parent window. And then build relationship between the testee window and the fake parent window.Window fakeParentWindow = new Window();
Foo testee = new Foo();
fakeParentWindow.Content = testee; // if testee is a kind of UIElement
testee.Owner = fakeParentWindow; // if testee is a kind of Window
fakeParentWindow.Show();
testee.Show(); // if it's a Window
If the testee is a Window, you can let it be the child window of the fakeParentWindow by assign fakeParentWindow to testee's property Owner. Or just do nothing you will get a top window testee. Don't forget to call Show() if it is a Window.
That's not everything of initializing a stage for your unit test. There are at least two threads you may interested in
- Main thread
- The worker thread running as an agent for your unit test case (I don't know why it is called an agent thread)
Dispatcher.CurrentDispatcher.BeginInvoke(
DispatcherPriority.Background,
new DispatcherOperationCallback(CarryOutTestSteps),
null);
System.Windows.Threading.Dispatcher.Run();
Since Dispatcher.Run() will block the test method, you have to invoke your test steps via CurrentDispatcher.BeginInvoke() in order to starting test. Your test steps will still be processed in the worker thread, but it will be processed as a dispatcher work item.By now, your window is showing.
Don't put Dispatcher.Run() into TestInitialize(), because Dispatcher.Run() will also blocks the thread and your test method won't get the chance to run.
Quit the Unit Test
Soon you will find that the unit test won't quit even the dispatcher work item has been completed, and even you close the windows manually. The thread is still enjoying pumping messages. To tell it to stop doing stupid things, just call Dispatcher.ExitAllFrames() when you finished all test steps:System.Windows.Threading.Dispatcher.ExitAllFrames();
Everything looks good, but... you will get an exception during the thread's termination. The exception says:I searched on the Internet. Eventually I found that was a bug of .Net Framework. A work around came from Visual Studio Product Team is calling CurrentDispatcher.InvokeShutdown() from TestCleanup()."An unhandled exception of type 'System.Runtime.InteropServices.InvalidComObjectException' occurred in PresentationCore.dll Additional information: COM object that has been separated from its underlying RCW cannot be used."
[TestCleanup]
public void TestCleanup()
{
System.Windows.Threading.Dispatcher.CurrentDispatcher.InvokeShutdown();
}
Be careful, .Net Framework may be changed letting this work around unnecessary.