我有一个MVVM-lite应用程序,我想要单元可测试.该模型使用System.Timers.Timer,因此更新事件最终在后台工作线程上.这个单元测试很好,但是在运行时抛出了System.NotSupportedException“这种类型的CollectionView不支持从与dispatcher线程不同的线程更改其SourceCollection.”我曾希望MVVM-lite类Threading.dispatcherHelper可以解决问题,但调用dispatcherHelper.CheckBeginInvokeOnUI导致我的单元测试失败.这是我在视图模型中最终得到的代码
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); } } }
我在http://kentb.blogspot.com/2009/04/mvvm-infrastructure-viewmodel.html中尝试过这个技巧,但在单元测试期间对dispatcher.Currentdispatcher上的Invoke调用无法运行,因此失败了.这就是为什么我在运行测试而不是应用程序时直接调用辅助方法的原因.
这可能不对 – viewmodel不应该关心它的调用位置.任何人都可以看到为什么Kent Boogaart的调度程序方法和MVVM-lite dispatcherHelper.CheckBeginInvokeOnUI都不能在我的单元测试中工作?
解决方法
我是这样做的:
class Myviewmodel() { private readonly SynchronizationContext _syncContext; public Myviewmodel() { _syncContext = SynchronizationContext.Current; // or use DI ) ... public void SomeTimerEvent() { _syncContext.Post(_ => UpdateUi(),null); } }
默认上下文将是测试中的线程池和UI中的调度程序.如果您想要其他一些行为,也可以轻松创建自己的测试上下文.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。