前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在单元测试中使用 Dispatcher.Invoke/InvokeAsync?

如何在单元测试中使用 Dispatcher.Invoke/InvokeAsync?

作者头像
walterlv
发布2018-09-18 13:05:07
1.3K0
发布2018-09-18 13:05:07
举报

如何在单元测试中使用 Dispatcher.Invoke/InvokeAsync?

发布于 2017-11-07 13:02 更新于 2018-08-19 11:08

对于部分涉及到 WPF UI 的部分,单元测试一般都难以进行。但是,如果只是使用到其中的 UI 线程调度,那就稍微容易一些。不过为了找到这个方法我做了很多天的尝试。

本文将提供一种在单元测试中运行 Dispatcher 的方法,以便能够在单元测试中测试到 Invoke/InvokeAsync 是否按要求执行。


我第一个想到的是在当前函数中执行 Dispatcher.Run,但是 Run 之后就阻塞了,我还怎么测试呢?

于是我又想到我上个月写的辅助方法 UIDispatcher.RunNewAsync(),在后台创建一个运行起来的 Dispatcher。参见我博客 如何实现一个可以用 await 异步等待的 Awaiter - walterlvUIDispatcher 的实现。

UIDispatcher
UIDispatcher

这方法确实可行,可以 await。然而单元测试中只有一个单元测试可以通过,无论什么测试,只有第一个 Run 起来的可以通过,其它的全部无法完成(已知运行中,无法退出单元测试)。


最后,在 c# - Using the WPF Dispatcher in unit tests - Stack Overflow 发现其实可以先 InvokeRun,这样,即便是当前的单元测试线程也是可以正常完成的。

private void RunInDispatcher(Action action)
{
    var dispatcher = Dispatcher.CurrentDispatcher;
    var frame = new DispatcherFrame();
    dispatcher.InvokeAsync(() => action(dispatcher));
    dispatcher.InvokeAsync(() => frame.Continue = false, DispatcherPriority.Background);
    Dispatcher.PushFrame(frame);
}

这个方法借鉴了此前我和我朋友研究过的 WPF DoEvents(虽然已被弃用):


于是,单元测试可以这样做:

[TestMethod]
public void TestSomething_SomethingHappened()
{
    RunInDispatcher(async dispatcher =>
    {
        // 做一些事情。
        // 然后……
        dispatcher.InvokeAsync(action);
        // 然后干些啥……
        // 然后等待 Measure/Arrange。
        await Dispatcher.Yield();
        // 然后再验证值。
        Assert.AreEqual(a, b);
    });
}

Yield 的意思可以参见我的另一篇博客 出让执行权:Task.Yield, Dispathcer.Yield - walterlv

以上。


参考资料

本文会经常更新,请阅读原文: https://walterlv.com/post/run-dispatcher-in-unit-test.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (walter.lv@qq.com)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-11-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 如何在单元测试中使用 Dispatcher.Invoke/InvokeAsync?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档