C# 从unittest调用时,Application.Current为null

C# 从unittest调用时,Application.Current为null,c#,wpf,unit-testing,C#,Wpf,Unit Testing,我有一个方法,我正试图从单元测试中调用它。 在现实生活中,此方法将从后台线程运行。它使用一些代码在UI线程的调用更新中启动(使用Application.Current.Dispatcher.BeginInvoke…) 但是,Application.Current在从单元测试调用时为null 我真的不知道应该在所有要修复的问题周围放置一个if(Application.Current!=null) 还有别的办法吗 _statusUpdates是一个可观察的集合 下面是我希望测试的方法中的代码部分(公

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

但是,
Application.Current
在从单元测试调用时为
null

我真的不知道应该在所有要修复的问题周围放置一个
if(Application.Current!=null)

还有别的办法吗

_statusUpdates是一个可观察的集合

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


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


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

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


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

如前所述,在单元测试期间,您根本不会有
应用程序类

也就是说,我认为这里有一个问题需要解决——在您的示例中,通过使用依赖于定义的静态属性的代码,您现在与该类的特定实现紧密耦合,即WPF
应用程序
类,你不需要去的地方

即使您只是简单地将“当前根调度器”的概念包装在一个
单例
风格的类包装器中,现在您也有了一种方法,可以将自己从
应用程序
类的变幻莫测中分离出来,并直接处理您关心的问题,即
调度器

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

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

好的,现在这个实现只比以前稍微好一点,但至少您现在对类型的访问有了更好的控制,并且不再严格依赖于
应用程序
实例的存在。

以下代码片段适合我:

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

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

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

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


@SonerGonul:-)你纠正了所有的问题,伙计。你是一个很好的人如果你在做单元测试,这个应用程序有没有被实例化过?如果应用程序刚刚启动或关闭(而应用程序还没有构建,或者已经被销毁),我通常会遇到这样的问题。哦,我想我的问题是重复的。抱歉:@SonerGönül嗨,我在格式方面犯了什么错误?让我知道,这样我就可以确保下次不会这样做,因为我认为我已经正确地完成了格式设置。@SonerGönül是的,但它不会告诉我之前做错了什么,因为我只能看到您编辑的版本?不管怎样,我还是要读一读这个链接。我不同意这种观点。只要运行WPF应用程序,Application.Current.Dispatcher就会存在。除非您编写的代码将在Windows应用商店应用程序和Windows桌面应用程序中使用,否则就不存在“紧密耦合”。如果您正在编写用于WPF应用程序的代码,那么像这样访问静态资源是完全可以接受的。。。事实并非如此。如果启动一个应用程序(在单独的AppDomain中),那么单元测试中将有一个当前的应用程序。此外,使用application.current.Dispatcher的原因可能是因为您需要访问UI元素,所以不仅仅是任何Dispatcher都会这样做。这个答案非常受欢迎。我将调用放在
[ClassInitialize]
方法中,它工作得非常好!必须在单元测试项目中添加对
PresentationFramework.dll
的引用。它在没有关闭模式(xUnit、.Net Framework 4.7.2)的情况下运行良好。到目前为止,在dotnet5上运行良好,我想访问
Application.Current.Windows
手动新建窗口的地方,引用在该集合中更新。我喜欢这个答案,我可以这样在ViewModel中编写代码:
private static Dispatcher=>Application.Current?.Dispatcher??Dispatcher.CurrentDispatcher然后只要在需要的地方引用即可。
if (System.Windows.Application.Current == null) 
  { new System.Windows.Application { ShutdownMode = ShutdownMode.OnExplicitShutdown }; }