wpf 从单元测试调用时,Application.Current 为 null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14837784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 07:29:16  来源:igfitidea点击:

Application.Current is null when calling from a unittest

c#wpfunit-testing

提问by DermFrench

I have a method that I'm trying to call from a unit test. This method will in real life be run from a background thread. It uses some code to kick off in the invoke updates to the UI thread (using Application.Current.Dispatcher.BeginInvoke.... ).

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

However Application.Currentis nullwhen being called from the unit tests.

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

I don't really what to put an if (Application.Current !=null)around everything to fix.

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

Is there any other way around this?

有没有其他办法解决这个问题?

_statusUpdates is an ObservableCollection

_statusUpdates 是一个 ObservableCollection

Below is the part of the code in the method I'm looking to test (it is more of an integration test than a unit test to be fair).

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

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

采纳答案by JerKimball

As already stated, you simply won't have an Applicationclass during unit tests.

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

That said, there's an issue here I think needs addressing - by having code that relies on a defined static property, in your case Application.Current.Dispatch, you are now verytightly coupled to the specific implementation of that class, namely the WPF Applicationclass, where you do not need to be.

也就是说,我认为这里有一个问题需要解决 - 通过使用依赖于已定义静态属性的代码,在您的情况下Application.Current.Dispatch,您现在与该类的特定实现(即 WPF类)非常紧密地耦合Application在一起,而您没有需要。

Even if you simply wrap the idea of "the current root dispatcher" in a Singleton-style class wrapper, now you have a way of decoupling yourself from the vagaries of the Applicationclass and dealing directly with what you care about, a Dispatcher:

即使您简单地将“当前根调度程序”的想法Singleton包装在一个样式类包装器中,现在您也有一种方法可以将自己与Application类的变幻无常并直接处理您关心的内容,a Dispatcher

Note, there are MANY MANY ways to write this, I'm just putting up the simplest possible implementation; hence, I will not be doing any multithreaded safety checks, etc.

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

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

Ok, now this implementation is only slightlybetter than before, but at least you now have finer control over access to the type and are no longer strictly dependent on the existence of an Applicationinstance.

好了,现在这个实现只是稍微比以前好多了,但至少你现在有超过访问类型更精细的控制,并不再完全依赖于是否存在Application实例。

回答by Shea

The following code snippet works for me:

以下代码片段对我有用:

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

IIRC, I had a problem where Application was null using a WPF control embedded in a WinForms application and that code snippet was suggested as a solution to the problem in another question on StackOverflow (sorry, can not find the source). It solves the same problem in unit tests (and I don't believe the ShutdownMode property needs to be explicitly set in that case).

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

回答by kaqq

Use Dispatcher.CurrentDispatcherinstead of Application.Current.Dispatcher

使用 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.

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

回答by Peter Ritchie

You will not have an Application object in a unit-test runner. These are usually "console" based applications that simply run and execute non-UI code ("units").

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

I suggest you don't use a unit test framework to test UI-specific information, I suggest a automated UI testing framework to do that.

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

回答by sircodesalot

So the issue here is that somewhere your Application object has to be created. So you need to find where the System.Windows.Application(or some descendent) class is being instantiated.

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

If the project was built from a template, then you'll probably find this class in the App.xaml file. You just need to make sure that this gets instantiated somehow. Else, search your entire project for an Applicationclass, and then you'll have to instantiate it manually. Should fix it.

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