c# - 从自己的 AppDomain 中的单元测试启动 WPF 应用程序

标签 c# wpf serialization nunit appdomain

我正在尝试从 nunit 运行 WPF 应用程序。由于每个 AppDomain 只能运行一个应用程序,因此我在每次验收测试时实例化一个新的 AppDomain。当我这样做时,我遇到了序列化异常。

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();
        }
    }
}

我现在收到的异常:

System.Runtime.Serialization.SerializationException : Type is not resolved for member 'Tests.ApplicationTests,Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

我创建了测试类[Serialized],但这也没有帮助。

非常感谢您的帮助。我只是想从NUnit测试启动我的WPF应用程序,以便我可以为我的应用程序编写验收测试。我不断地遇到不同的墙壁,最终我选择的任何道路似乎都会通向死胡同......

提前非常感谢,

巴斯

最佳答案

AppDomains 是 .NET 中软件隔离的进程。这意味着您不能只从另一个 AppDomain 引用属于一个 AppDomain 的对象。对象可以按值(序列化)复制,也可以使用 MarshalByRefObject 通过引用复制。由于 WPF 的对象不是其中任何一个,因此您无法在 AppDomain 中移动它们。

为了您的测试目的,您可以使用更简单的方法:在新 AppDomain 中运行所有内容,并使用 SetDataGetData 方法传输数据以断言.

[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();
}

关于c# - 从自己的 AppDomain 中的单元测试启动 WPF 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23454023/

相关文章:

c# - 使用什么产品文件夹名称?

c# - 将整数转换为对象并返回会导致 InvalidCastException

c# - WPF 新手,如何在我的表单中创建这些彩色条?

c# - 如何在 .NET C# 中转换反序列化 php 对象

c# - 将对象转换为对象数组

c# - 使用自定义 ContractResolver,如何在将 null JSON 属性反序列化为值类型成员时设置默认值而不是 null?

c# - Windows 窗体中的网络浏览器的 AccessViolationException

WPF ScrollViewer 将控件推出窗口

wpf - 为什么 ItemsPresenter 会覆盖我的 DataGrid 的前景样式?

objective-c - 如何将 Google Protocol Buffer 集成到 xCode 项目中?