Application.Current имеет значение null при вызове с unittest
У меня есть метод, который я пытаюсь вызвать из unit test.
Этот метод в реальной жизни будет запущен из фонового потока. Он использует некоторый код для запуска в вызове обновлений потока пользовательского интерфейса (используя Application.Current.Dispatcher.BeginInvoke
....).
Однако Application.Current
является null
при вызове из модульных тестов.
На самом деле, я действительно не помещаю if (Application.Current !=null)
вокруг всего, чтобы исправить.
Есть ли другой способ?
_statusUpdates - это ObservableCollection
Ниже приведена часть кода в методе, который я пытаюсь проверить (это скорее интеграционный тест, чем unit test).
Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (EventHandler)delegate
{
_statusUpdates.Add(new StatusUpdate
{
DateTime = DateTime.Now,
Message = "Checking For Messages"
});
}, null, null);
Ответы
Ответ 1
Как уже было сказано, вы просто не будете иметь класс Application
во время модульных тестов.
Тем не менее, здесь проблема, о которой я думаю, требует адресации - имея код, который полагается на определенное статическое свойство, в вашем случае Application.Current.Dispatch
, вы теперь очень тесно связаны с конкретной реализацией этого класса, а именно класс WPF Application
, где вам не нужно быть.
Даже если вы просто оберните идею "текущего диспетчера корней" в оболочке класса Singleton
-style, теперь у вас есть способ отделить себя от капризов класса Application
и напрямую обращаться с тем, что вы заботиться о, 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
.
Ответ 2
Следующий фрагмент кода работает для меня:
if (System.Windows.Application.Current == null)
{ new System.Windows.Application { ShutdownMode = ShutdownMode.OnExplicitShutdown }; }
IIRC, у меня была проблема, когда Application было null, используя элемент управления WPF, встроенный в приложение WinForms, и этот фрагмент кода был предложен как решение проблемы в другом вопросе в StackOverflow (извините, не могу найти источник). Он решает ту же проблему в модульных тестах (и я не считаю, что свойство ShutdownMode должно быть явно задано в этом случае).
Ответ 3
У вас не будет объекта Application в run-run unit. Обычно это "консольные" приложения, которые просто запускают и выполняют код, отличный от UI ( "единицы" ).
Я предлагаю вам не использовать фреймворк unit test для проверки информации, специфичной для пользовательского интерфейса, для этого я предлагаю схему автоматического тестирования пользовательского интерфейса.
Ответ 4
Итак, проблема здесь в том, что где-то должен быть создан ваш объект приложения. Поэтому вам нужно найти, где создается экземпляр класса System.Windows.Application
(или нескольких потомков).
Если проект был создан из шаблона, вы, вероятно, найдете этот класс в файле App.xaml. Вам просто нужно убедиться, что это каким-то образом создается. Else, выполните поиск всего проекта для класса Application
, а затем вам придется создавать его вручную. Должен исправить это.