Вот один для навязчивых фанатов.У меня есть этот метод:
public void RefreshMelts()
{
MeltsAvailable.Clear();
ThreadPool.QueueUserWorkItem(delegate
{
Dispatcher.BeginInvoke((ThreadStart)delegate
{
eventAggregator.GetEvent<BusyEvent>().Publish(true);
eventAggregator.GetEvent<StatusMessageEvent>().Publish(
new StatusMessage("Loading melts...", MessageSeverity.Low));
});
try
{
IList<MeltDto> meltDtos = meltingAppService.GetActiveMelts();
Dispatcher.Invoke((ThreadStart)delegate
{
foreach (MeltDto availableMelt in meltDtos)
{
MeltsAvailable.Add(availableMelt);
}
OnPropertyChanged("MeltsAvailable");
eventAggregator.GetEvent<BusyEvent>().Publish(false);
eventAggregator.GetEvent<StatusMessageEvent>().Publish(
new StatusMessage("Melts loaded", MessageSeverity.Low));
});
}
catch (ApplicationException ex)
{
log.Error("An error occurred in MeltsViewModel when attempting to load melts", ex);
Dispatcher.Invoke((ThreadStart)delegate
{
MeltsAvailable.Clear();
eventAggregator.GetEvent<StatusMessageEvent>().Publish(
new StatusMessage("Melt data could not be loaded because an error occurred; " +
"see the application log for detail",
MessageSeverity.High));
eventAggregator.GetEvent<BusyEvent>().Publish(false);
});
}
});
}
Это определено в пользовательском элементе управления WPF.MeltsAvailable является наблюдаемой коллекцией MeltDtos.Этот код прекрасно работает при запуске в самом приложении.
Проблема в том, что я хотел бы создать модульное тестирование, используя NMock, для проверки результатов этого метода, в частности, после вызова MeltsAvailable.В собственности есть несколько предметов.Вот метод теста:
[TestMethod]
public void GetAvailableMeltsTest()
{
MeltDto mockMelt1 = new MeltDto();
MeltDto mockMelt2 = new MeltDto();
mockMelt1.MeltIdentifier = "TST0001";
mockMelt2.MeltIdentifier = "TST0002";
IList<MeltDto> availableMelts = new List<MeltDto>();
availableMelts.Add(mockMelt1);
availableMelts.Add(mockMelt2);
Expect.Exactly(1).On(service).Method("GetActiveMelts").Will(Return.Value(availableMelts));
MeltsViewModel vm = new MeltsViewModel(aggregator, logger, service, configManagerFactory); // All of these are mock objects
vm.RefreshMelts();
Thread.Sleep(millisecondDelayForEventPublish * 100);
mockery.VerifyAllExpectationsHaveBeenMet();
Assert.AreEqual(vm.MeltsAvailable.Count, 2);
Assert.AreEqual(vm.MeltsAvailable[0].MeltIdentifier, "TST0001");
Assert.AreEqual(vm.MeltsAvailable[1].MeltIdentifier, "TST0002");
}
Тест последовательно завершается неудачей на первом Assert.AreEqual.vm.MeltsAvailable в этот момент пуст.
Если я удаляю все потоки и оставляю это так:
public void RefreshMelts()
{
MeltsAvailable.Clear();
IList<MeltDto> meltDtos = meltingAppService.GetActiveMelts();
foreach (MeltDto availableMelt in meltDtos)
{
MeltsAvailable.Add(availableMelt);
}
OnPropertyChanged("MeltsAvailable");
}
Тест проходит.
Итак, очевидно,есть что-то, что ему не нравится в потоках - но даже включив Debug-> Exceptions-> CLR Exceptions-> Thrown и отключив Just My Code, я не получаю никаких исключений в RefreshMelts.
Самое странное, что вызов Dispatcher.Invoke, когда я загружаю объекты MeltDto в коллекцию MeltsAvailable, кажется, никогда не вызывается.Я могу покрыть весь раздел точками останова, и они никогда не будут поражены.Увеличение резьбы. Время ожидания в моем тесте даже до десяти секунд ничего не меняет.
Почему?Почему этот раздел не выполняется, почему я не могу войти в него или взломать его, почему я не получаю исключения, почему он отлично работает при выполнении, но не в тесте?
Большое спасибо, Стив