I've an MVVM-lite application that I'd like to have unit testable. The model uses a System.Timers.Timer and so the update event ends up on a background worker thread. This unit-tested fine, but at runtime threw the System.NotSupportedException "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread." I had hoped that the MVVM-lite class Threading.DispatcherHelper would fix things but calling DispatcherHelper.CheckBeginInvokeOnUI results in my unit test failing. Here's the code I've ended up with in the view model
private void locationChangedHandler(object src, LocationChangedEventArgs e)
{
if (e.LocationName != this.CurrentPlaceName)
{
this.CurrentPlaceName = e.LocationName;
List<FileInfo> filesTaggedForHere = Tagger.FilesWithTag(this.CurrentPlaceName);
//This nextline fixes the threading error, but breaks it for unit tests
//GalaSoft.MvvmLight.Threading.DispatcherHelper.CheckBeginInvokeOnUI(delegate { updateFilesIntendedForHere(filesTaggedForHere); });
if (Application.Current != null)
{
this.dispatcher.Invoke(new Action(delegate { updateFilesIntendedForHere(filesTaggedForHere); }));
}
else
{
updateFilesIntendedForHere(filesTaggedForHere);
}
}
}
private void updateFilesIntendedForHere(List<FileInfo> filesTaggedForHereIn)
{
this.FilesIntendedForHere.Clear();
foreach (FileInfo file in filesTaggedForHereIn)
{
if (!this.FilesIntendedForHere.Contains(file))
{
this.FilesIntendedForHere.Add(file);
}
}
}
I did try the trick in http://kentb.blogspot.com/2009/04/mvvm-infrastructure-viewmodel.html but the call to Invoke on the Dispatcher.CurrentDispatcher failed to run during the unit test and so it failed. That's why I'm calling the helper method directly if the run is in a test and not an application.
This can't be right - the ViewModel shouldn't care where it's being called from. Can anyone see why neither Kent Boogaart's dispatcher method nor the MVVM-lite DispatcherHelper.CheckBeginInvokeOnUI work in my unit test?