26

我有一个试图从单元测试中调用的方法。此方法将在现实生活中从后台线程运行。它使用一些代码来启动对 UI 线程的调用更新(使用Application.Current.Dispatcher.BeginInvoke.... )。

但是Application.Currentnull当从单元测试中调用时。

我真的不知道要if (Application.Current !=null)解决什么问题。

有没有其他方法可以解决这个问题?

_statusUpdates 是一个 ObservableCollection

下面是我要测试的方法中的部分代码(公平地说,它更像是集成测试而不是单元测试)。

Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (EventHandler)delegate
{
    _statusUpdates.Add(new StatusUpdate
    {
        DateTime = DateTime.Now,
        Message = "Checking For Messages"
    });
}, null, null);
4

5 回答 5

27

以下代码片段适用于我:

if (System.Windows.Application.Current == null) 
  { new System.Windows.Application { ShutdownMode = ShutdownMode.OnExplicitShutdown }; }

IIRC,我遇到了一个问题,即使用嵌入在 WinForms 应用程序中的 WPF 控件,Application 为空,并且在 StackOverflow 上的另一个问题中建议使用该代码片段作为该问题的解决方案(抱歉,找不到源代码)。它解决了单元测试中的相同问题(而且我认为在这种情况下不需要显式设置 ShutdownMode 属性)。

于 2016-10-03T22:07:52.183 回答
13

如前所述,Application在单元测试期间您根本不会上课。

也就是说,这里有一个问题我认为需要解决 - 在你的情况下,通过拥有依赖于定义的静态属性的代码Application.Current.Dispatch,你现在非常紧密地耦合到该类的特定实现,即 WPFApplication类,你不需要需要。

即使您只是将“当前根调度程序”的想法包装在一个Singleton-style 类包装器中,现在您也可以将自己从Application类的变幻莫测中解耦并直接处理您关心的内容,a Dispatcher

注意,有很多方法可以写这个,我只是提出最简单的实现;因此,我不会进行任何多线程安全检查等。

public class RootDispatcherFetcher
{
     private static Dispatcher _rootDispatcher = null;

     public static Dispatcher RootDispatcher
     {
         get 
         {
             _rootDispatcher = _rootDispatcher ??
                 Application.Current != null 
                     ? Application.Current.Dispatcher
                     : new Dispatcher(...);
             return _rootDispatcher;
         }
         // unit tests can get access to this via InternalsVisibleTo
         internal set
         {
             _rootDispatcher = value;
         }
     }
}

好的,现在这个实现只比以前稍微好一点,但至少你现在可以更好地控制对类型的访问,并且不再严格依赖于Application实例的存在。

于 2013-02-12T17:33:12.840 回答
10

使用 Dispatcher.CurrentDispatcher代替Application.Current.Dispatcher

Gets the System.Windows.Threading.Dispatcher for the thread currently executing and creates a new System.Windows.Threading.Dispatcher if one is not already associated with the thread.

于 2018-05-17T14:46:42.340 回答
0

单元测试运行器中不会有 Application 对象。这些通常是基于“控制台”的应用程序,它们简单地运行和执行非 UI 代码(“单元”)。

我建议您不要使用单元测试框架来测试特定于 UI 的信息,我建议使用自动化 UI 测试框架来做到这一点。

于 2013-02-12T17:17:01.923 回答
-1

所以这里的问题是必须在某个地方创建您的 Application 对象。因此,您需要找到System.Windows.Application实例化(或某些后代)类的位置。

如果项目是从模板构建的,那么您可能会在 App.xaml 文件中找到此类。您只需要确保它以某种方式被实例化。否则,在整个项目中搜索一个Application类,然后您必须手动实例化它。应该修复它。

于 2013-02-12T17:12:52.203 回答