これは、そこにある糸脱毛中毒者のためのものです。私はこの方法を持っています:
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のObservableCollectionです。このコードは、アプリケーション自体で実行すると美しく機能します。
問題は、このメソッドの結果を検証するために、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");
}
テストに合格します。
したがって、明らかに、スレッドには気に入らない点がありますが、[デバッグ]->[例外]->[CLR例外]->[スロー]をオンにし、[マイコードのみ]をオフにしても、RefreshMeltsでは例外はまったく発生しません。
最も奇妙な部分は、MeltDtoオブジェクトをMeltsAvailableコレクションにロードするDispatcher.Invoke呼び出しが呼び出されていないように見えることです。セクション全体をブレークポイントで覆うことができますが、ブレークポイントがヒットすることはありません。私のテストでThread.Sleep時間を10秒まで上げても、何も変わりません。
なんで?そのセクションが実行されないのはなぜですか、ステップインまたはブレークできないのはなぜですか、例外が発生しないのはなぜですか、実行では正常に機能するのにテストでは機能しないのはなぜですか?
どうもありがとう、スティーブ