从unittest调用时,Application.Current为null

我有一个方法,我试图通过unit testing调用。 这种方法在现实生活中将从后台线程运行。 它使用一些代码启动对UI线程的调用更新(使用Application.Current.Dispatcher.BeginInvoke ….)。

但是,从unit testing中调用Application.Currentnull

我真的不想把if (Application.Current !=null)放在要解决的所有问题上。

还有其他方法吗?

_statusUpdates是一个ObservableCollection

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

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

如前所述,在unit testing期间,您根本就没有Application类。

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

即使你只是在Singleton风格的类包装器中包含“当前根调度程序”的概念,现在你有办法将自己与Application类的变幻莫测,并直接处理你关心的事情, Dispatcher

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

 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实例的存在。

以下代码段适用于我:

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

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

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

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

使用Dispatcher.CurrentDispatcher而不是Application.Current.Dispatcher

获取当前正在执行的线程的System.Windows.Threading.Dispatcher,并创建一个新的System.Windows.Threading.Dispatcher(如果尚未与该线程关联)。

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

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