首页 > 解决方案 > 单元测试基于 Prism 的 WPF 应用程序

问题描述

我想对基于 Prism 的 WPF 应用程序进行单元测试。这是一个包含多个项目的巨大应用程序。每个项目都基于具有 ViewModel/Views 的 MVVM 设计模式。此应用程序使用 Bootstrapper 进行初始化,使用区域概念并具有事件处理。

我尝试使用 xunit。我拿了一个项目并添加了一个相应的测试项目,我尝试在其中实现一个测试用例。在测试用例中,我创建了一个 View 类的实例(代码隐藏)并尝试从该类调用一个方法。我收到以下错误:

*****************

------ Run test started ------
[xUnit.net 00:00:00.3423646]   Discovering: Demo.Test
[xUnit.net 00:00:01.2217151]   Discovered:  Demo.Test
[xUnit.net 00:00:01.2260195]   Starting:    Demo.Test
[xUnit.net 00:00:02.5700093]     TestClassLibrary.TestDemo.TestCase1 [FAIL]
[xUnit.net 00:00:02.5722687]       System.InvalidOperationException : The calling thread must be STA, because many UI components require this.
[xUnit.net 00:00:02.5739943]       Stack Trace:
[xUnit.net 00:00:02.5749537]            at System.Windows.Input.InputManager..ctor()
[xUnit.net 00:00:02.5754038]            at System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
[xUnit.net 00:00:02.5757829]            at System.Windows.Input.KeyboardNavigation..ctor()
[xUnit.net 00:00:02.5762326]            at System.Windows.FrameworkElement.FrameworkServices..ctor()
[xUnit.net 00:00:02.5766521]            at System.Windows.FrameworkElement.EnsureFrameworkServices()
[xUnit.net 00:00:02.5771316]            at System.Windows.FrameworkElement..ctor()
[xUnit.net 00:00:02.5775379]            at System.Windows.Controls.Control..ctor()
[xUnit.net 00:00:02.5792034]            at System.Windows.Controls.UserControl..ctor()
[xUnit.net 00:00:02.5796505]            at Demo.Views.DemoLandingPage..ctor(IDemoViewModel vwModel, IEventAggregator eventAggregator, ISharedService sharedService)
[xUnit.net 00:00:02.5801319]         Demo.Test\Class1.cs(65,0): at TestClassLibrary.TestDemo.<TestCase1>b__0_0()
[xUnit.net 00:00:02.5805993]            at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
[xUnit.net 00:00:02.5810366]            at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
[xUnit.net 00:00:02.5814870]            at System.Windows.Threading.DispatcherOperation.InvokeImpl()
[xUnit.net 00:00:02.5819703]            at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
[xUnit.net 00:00:02.5825284]            at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
[xUnit.net 00:00:02.5831148]            at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
[xUnit.net 00:00:02.5834395]            at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
[xUnit.net 00:00:02.5837782]            at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
[xUnit.net 00:00:02.5842970]            at System.Windows.Threading.DispatcherOperation.Invoke()
[xUnit.net 00:00:02.5848709]            at System.Windows.Threading.Dispatcher.ProcessQueue()
[xUnit.net 00:00:02.5852488]            at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
[xUnit.net 00:00:02.5857359]            at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
[xUnit.net 00:00:02.5863023]            at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
[xUnit.net 00:00:02.5867150]            at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
[xUnit.net 00:00:02.5872700]            at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
[xUnit.net 00:00:02.5877817]            at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
[xUnit.net 00:00:02.5883386]            at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
[xUnit.net 00:00:02.5889004]            at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
[xUnit.net 00:00:02.5894200]            at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
[xUnit.net 00:00:02.5899856]            at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
[xUnit.net 00:00:02.5905323]            at System.Windows.Threading.DispatcherOperation.Wait(TimeSpan timeout)
[xUnit.net 00:00:02.5910927]            at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherOperation operation, CancellationToken cancellationToken, TimeSpan timeout)
[xUnit.net 00:00:02.5915975]            at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
[xUnit.net 00:00:02.5921129]         Demo.Test\Class1.cs(63,0): at TestClassLibrary.TestDemo.TestCase1()
[xUnit.net 00:00:02.6178918]   Finished:    Demo.Test
========== Run test finished: 1 run (0:00:03.1364452) ==========

*****************

这是测试用例代码:

************* Class1.cs ******
namespace TestClassLibrary
{
    public class TestDemo
    {
[Fact]
        public void TestCase1()
        {
                if (Application.Current == null)
                {
                    if (System.Windows.Application.Current == null)
                    {
                        new System.Windows.Application { ShutdownMode = ShutdownMode.OnExplicitShutdown };
                    }
                }

(LINE 63)                    Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
                {
(LINE 65)                    DemoLandingPage dem = new DemoLandingPage(null, null, null);
                    List<string> countryList = dem.GetCountryList("CountryList");
                    bool ret = searchCountry("Test", countryList);
                    Assert.True(ret == true);
                }));

        }

        bool searchCountry(string country, List<string> list)
        {
            return list.Contains(country);
        }    

*************

我想知道:

是否可以对基于 Prism 的 WPF 应用程序进行单元测试?如果是这样,您能否让我知道我应该采用什么方法来测试此应用程序。任何指针或文档/链接都会有很大帮助。

谢谢

标签: c#wpfxunit

解决方案


推荐阅读