Reputation: 14912
I am trying to run a WPF App from nunit. Since I only can run one App per AppDomain I instantiate a new AppDomain per acceptance test. When I do that, I run into serialization exceptions.
namespace Tests
{
[TestFixture, RequiresSTA, Serializable]
public class ApplicationTests
{
private MainWindow mainWindow;
private bool guiVisible;
private App app;
[TestCase("app domain name for instance of App")]
[TestCase("app domain name for another instance of App")]
public void ApplicationTest(string name)
{
AppDomain appDomain = AppDomain.CreateDomain(name);
//appDomain.ExecuteAssembly(@"C:\Users\bp\Documents\Visual Studio 2013\Projects\WpfApplication1\WpfApplication1\bin\Debug\WpfApplication1.exe");
CrossAppDomainDelegate action = () =>
{
app = new App();
app.InitializeComponent();
app.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => AppOnActivated(null, null)));
app.Run();
};
appDomain.DoCallBack(action);
}
private void AppOnActivated(object sender, EventArgs eventArgs)
{
if (!guiVisible)
{
mainWindow = (MainWindow)Application.Current.MainWindow;
mainWindow.ButtonViewModel = new ButtonViewModel();
mainWindow.ButtonViewModel.Name = "bla";
guiVisible = true;
}
app.Shutdown();
}
}
}
The exception I receive now:
System.Runtime.Serialization.SerializationException : Type is not resolved for member 'Tests.ApplicationTests,Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
I made the test class [Serializable]
which does not help either.
Help is very much appreciated. I just want to start my WPF application from an NUnit
test so that I can write acceptance tests for my application. I keep running into different walls and eventually whatever path I choose seems to lead to a dead end...
Many thanks in advance,
Bas
Upvotes: 2
Views: 2810
Reputation: 22739
AppDomains are software-isolated processes in .NET. This means you can't just reference objects belonging to one AppDomain from another. Objects can be either copied by value (serialization) or by reference using MarshalByRefObject
. Since WPF's objects are neither of those, you can't move them around AppDomains.
For your your testing purposes, you could use a simpler approach: run everything within the new AppDomain, and use the SetData
and GetData
methods to transfer data to assert on.
[TestCase("app domain name for instance of App")]
[TestCase("app domain name for another instance of App")]
public void ApplicationTest(string name)
{
AppDomain appDomain = AppDomain.CreateDomain(name,
AppDomain.CurrentDomain.Evidence,
AppDomain.CurrentDomain.SetupInformation);
appDomain.DoCallBack(StartApp);
Assert.IsTrue((bool)appDomain.GetData("GuiVisible"));
AppDomain.Unload(appDomain);
}
// using a static method instead of a lambda makes sure
// you haven't captured anything
private static void StartApp()
{
app = new App();
app.InitializeComponent();
app.Dispatcher.BeginInvoke(DispatcherPriority.Loaded,
new Action(() => AppOnActivated()));
app.Run();
}
private static void AppOnActivated()
{
var mainWindow = (MainWindow)Application.Current.MainWindow;
mainWindow.ButtonViewModel = new ButtonViewModel();
mainWindow.ButtonViewModel.Name = "bla";
AppDomain.CurrentDomain.SetValue("GuiVisible") = true;
app.Shutdown();
}
Upvotes: 4