我在ViewModel中有代码通过任务调用服务。 任务完成后,它将填充ObservableCollection。 问题是它正在等待任务完成,使用ContinueWith方法并提供TaskScheduler.FromCurrentSynchronizationContext作为任务调度程序,以便在UI线程上更新OC。
到目前为止一直很好,但是当谈到单元测试时,它会抛出一个异常,说“当前的SynchronizationContext可能不会被用作TaskScheduler”。 如果我在单元测试中使用模拟SynchronizationContext,那么ObservableCollection会抛出一个错误,因为它是根据调度程序线程进行更新的。
有什么方法可以解决这个问题吗?
感谢。
答案 0 :(得分:17)
这并不容易,但也不是那么难。你需要做的是启动一个作为STA设置的工作线程,然后在其上启动Dispatcher运行时。一旦你让那个工人坐在那里,你可以从单元测试线程向它发送工作,显然,这些线程没有为这种工作进行初始化。首先,这是您在测试设置中启动调度程序线程的方法:
this.dispatcherThread = new Thread(() =>
{
// This is here just to force the dispatcher infrastructure to be setup on this thread
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
{
Trace.WriteLine("Dispatcher worker thread started.");
}));
// Run the dispatcher so it starts processing the message loop
Dispatcher.Run();
});
this.dispatcherThread.SetApartmentState(ApartmentState.STA);
this.dispatcherThread.IsBackground = true;
this.dispatcherThread.Start();
现在,如果您想在测试清理中干净地关闭该线程,我建议您这样做,您只需执行以下操作:
Dispatcher.FromThread(this.dispatcherThread).InvokeShutdown();
所以,所有这些基础设施的东西都在这里,在测试中你需要做的就是在那个线程上执行。
public void MyTestMethod
{
// Kick the test off on the dispatcher worker thread synchronously which will block until the work is competed
Dispatcher.FromThread(this.dispatcherThread).Invoke(new Action(() =>
{
// FromCurrentSynchronizationContext will now resolve to the dispatcher thread here
}));
}
答案 1 :(得分:14)
将此添加到测试初始化中,以创建上下文:
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
答案 2 :(得分:0)
这使它更简单
TaskScheduler scheduler = Dispatcher.CurrentDispatcher.Invoke(TaskScheduler.FromCurrentSynchronizationContext)
然后您的代码可以显式使用scheduler
(在运行时使用TaskScheduler.FromCurrentSynchronizationContext()
初始化)