如何为使用 Application.Current.Dispatcher.Invoke 的方法编写 WPF 异步单元测试?

How to write a WPF async unit test for a method that uses Application.Current.Dispatcher.Invoke?

我们有一个用 WPF 编写的应用程序。 我正在尝试为一些在后台线程上 运行s 的代码编写单元测试。在这段代码的一些地方,我们需要在 UI 线程上做一些事情。在那些地方我们使用以下代码结构:

Application.Current.Dispatcher.Invoke(new Action(() =>
{
// do something on UI thread
}));

当我创建异步单元测试时,它似乎卡在了 Invoke 方法上。我想这是因为调度员不是 "dispatching"。我试图通过使用一个名为 DisaptcherUtil 的 class 来解决这个问题,该工具在 Internet 上的许多地方都有引用。但我无法让它发挥作用。我的代码的简化版本现在如下所示:

    [TestMethod]
    public async Task TestDispatcher()
    {
        new Application();

        DispatcherUtil.DoEvents();

        await Task.Run(() => MethodUsingDispatcher());
    }


    private void MethodUsingDispatcher()
    {
        Application.Current.Dispatcher.Invoke(new Action(() =>
        {
            Console.WriteLine("On the dispatchee thread!");
        }));

        Console.WriteLine("BAck to background trhead");
    }

    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)
        {
            Console.WriteLine("ExitFrame");

            ((DispatcherFrame)frame).Continue = false;
            return null;
        }
    }

当我 运行 测试调用 "TestDispatcher" 它只是挂起。

有人知道为什么会这样吗?这是执行此操作的正确方法还是我应该继续为我可以在测试中模拟的 Dispatcher 创建接口。我在一些地方看到过这样做。

我会说你应该将调度隐藏在接口后面并在单元测试中模拟它:

interface IDispatcher
{
    void Dispatch(Action action);
}

您可以在您的测试中轻松地模拟它并期望那些已调度的调用。

一个使用真正的调度程序并可以被你的应用程序使用的实现:

public class Dispatcher 
{
    public void Dispatch(Action action)
    {
        Application.Current.Dispatcher.Invoke(action);
    }
}