我正在尝试遵循 Using the WPF Dispatcher in unit tests 中的建议为了运行我的 nUnit 测试。
当我如下编写单元测试时,它有效:
[Test]
public void Data_Should_Contain_Items()
{
DispatcherFrame frame = new DispatcherFrame();
PropertyChangedEventHandler waitForModelHandler = delegate(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Data")
{
frame.Continue = false;
}
};
_myViewModel.PropertyChanged += waitForModelHandler;
Dispatcher.PushFrame(frame);
Assert.IsTrue(_myViewModel.Data.Count > 0, "Data item counts do not match");
}
但是,如果我尝试使用 DispatcherUtil 的建议,它不起作用:
[Test]
public void Data_Should_Contain_Items()
{
DispatcherUtil.DoEvents();
Assert.IsTrue(_myViewModel.Data.Count > 0, "Data item counts do not match");
}
public static class DispatcherUtil
{
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}
private static object ExitFrame(object frame)
{
((DispatcherFrame)frame).Continue = false;
return null;
}
}
当我使用 DispatcherUtil 时,似乎在数据准备好之前调用 ExitFrame 的时间过早。
我没有正确使用 DispatcherUtil 吗?这似乎是一种更好的方法来处理调度程序,而不是等待来自 View 模型的回调。
最佳答案
由于调度程序在单元测试中存在问题,我的解决方案是打破 View 模型对调度程序的依赖。我假设目前您有硬编码的引用,例如:
Dispatcher.CurrentDispatcher.BeginInvoke(..
调度程序是一个外部依赖项,不应成为单元测试的一部分 - 我们可以假设调度程序正常工作。
我会使用依赖注入(inject)(穷人、Unity 等)。
创建一个代表调度程序的合适接口(interface)。
创建一个包装真实调度程序的真实实现。
创建一个使用 Action.BeginInvoke 的假实现。
在假的中,您记录了所有返回给 BeginInvoke 调用的 IAsyncResults。
然后有一个辅助方法,它会等待所有调用完成,您可以在测试中使用它来等待完成。
或者有一个 View 模型基类做同样的事情。正常调用调度程序,但可以在测试期间被指示调用假的。
关于c# - 在单元测试中使用 WPF Dispatcher 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9336165/