30

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 .... ).

However Application.Current is null when being called from the unit tests.

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

Is there any other way around this?

_statusUpdates is an 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);
DermFrench
  • 3,968
  • 13
  • 43
  • 70
  • 1
    @SonerGonul :-) You correct all questions man. You're a fine person – Aniket Inge Feb 12 '13 at 17:03
  • If you're doing a unit test, is that Application ever being instantiated? Usually I run into a problem like this if the application is just being started up or shut down (and the application hasn't been built yet, or has already been destroyed). – sircodesalot Feb 12 '13 at 17:03
  • @sircodesalot Yes that is the problem Application.current is null, as I'm running from test. Is there any way I can force it to instantiate or something, rather than adding a load of checks for !=null all over the place? – DermFrench Feb 12 '13 at 17:05
  • 1
    D'oh I think my question is a duplicate. Sorry: http://stackoverflow.com/questions/1106881/using-the-wpf-dispatcher-in-unit-tests – DermFrench Feb 12 '13 at 17:08
  • @Aniket I wish not to but people who new in SO they don't read [faq] and [ask] clearly or they don't know/care about formatting. A question with good format is **always** getting more attention. – Soner Gönül Feb 12 '13 at 17:09
  • 1
    @SonerGönül Hi, what mistake did I make in formatting? Let me know so I can ensure I don't do it next time, as I thought I had my formatting correctly done. – DermFrench Feb 12 '13 at 17:14
  • @DermFrench You can check out http://stackoverflow.com/editing-help link for more formatting details. – Soner Gönül Feb 12 '13 at 17:29
  • 1
    @SonerGönül Yes but it won't tell me what I did wrong earlier, as I can only see the version you edited? I'll have a read of the link anyway. – DermFrench Feb 12 '13 at 17:38

5 Answers5

28

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).

Shea
  • 839
  • 1
  • 10
  • 17
  • 2
    big fan of this answer. I put the call in the `[ClassInitialize]` method and it works wonderfully! – Keith Dec 13 '18 at 21:21
  • Have to add reference to `PresentationFramework.dll` in unit test project. – Sinatr Nov 21 '19 at 13:41
  • It works well without ShutdownMode (xUnit, .Net Framework 4.7.2). – Lev Apr 30 '20 at 13:31
  • Works nice with dotnet5 so far where I want to access `Application.Current.Windows` where I new up a window manually, the reference is updated in that collection. – Andez May 05 '21 at 17:05
14

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

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 very tightly coupled to the specific implementation of that class, namely the WPF Application class, where you do not need to be.

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 Application class and dealing directly with what you care about, 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 slightly better 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 Application instance.

JerKimball
  • 16,584
  • 3
  • 43
  • 55
  • 4
    I disagree with this sentiment. Application.Current.Dispatcher is going to exist anytime you run a WPF application. Unless you write code that will be used, say, in a Windows Store App vs a Windows Desktop application, then there is no "tight coupling". I you are writing code that will be used for a WPF application, accessing static resources like this is perfectly acceptable. – ChrisCW Jul 29 '15 at 18:29
  • "As already stated, you simply won't have an Application class during unit tests." ... That is not true. If you start an application (in a separate AppDomain) you will have a current application within your Unit tests. – Wouter Schut Jun 09 '16 at 11:04
  • Also, the reason for using Application.Current.Dispatcher is probably because you need access to UI elements, so not just any dispatcher will do. – TamaMcGlinn Feb 16 '18 at 10:45
13

Use Dispatcher.CurrentDispatcher instead of 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.

kaqq
  • 345
  • 2
  • 7
0

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").

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.

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98
-1

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.

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 Application class, and then you'll have to instantiate it manually. Should fix it.

sircodesalot
  • 11,231
  • 8
  • 50
  • 83