【问题标题】:MVVM light Dispatcher unit testsMVVM light Dispatcher 单元测试
【发布时间】:2016-08-17 08:40:55
【问题描述】:

我有以下功能

 public void Reset()
 {
     DisableModule();
     DispatcherHelper.UIDispatcher.Invoke(() =>
     {
           PixelPointInfoCollection.Clear();
           PixelPointInfoCollection.Add(new PointViewModel());
     });
     _cachedPoints.Clear();
 }

以下代码在运行单元测试时卡在 Invoke() 方法中。

我看到一些关于在调度程序上创建自定义接口和在单元测试中模拟调度程序的文章。 例如http://blog.zuehlke.com/en/mvvm-and-unit-testing/

没有别的办法了吗?我有一个庞大的代码库。我现在真的需要更改所有内容吗?

更新 18.8.2016 现在这是我所做的,它正在工作

public static class AppServices
{

    public static IDispatcher Dispatcher { get; set; } 
    public static void Init(IDispatcher dispatcher)
    {
        Dispatcher = dispatcher;
    }
}

//this inteface is in order to overrcome MVVM light Dispatcher so we can mock it for unit tests
public interface IDispatcher
{
    void Invoke(Action action);
    void Invoke(Action action, DispatcherPriority priority);
    DispatcherOperation BeginInvoke(Action action);
}

public class DispatcherWrapper :IDispatcher
{
    public DispatcherWrapper()
    {
        DispatcherHelper.Initialize();
    }
    public void Invoke(Action action)
    {
        DispatcherHelper.UIDispatcher.Invoke(action);
    }

    public void Invoke(Action action, DispatcherPriority priority)
    {
        DispatcherHelper.UIDispatcher.Invoke(action, priority);
    }

    public DispatcherOperation BeginInvoke(Action action)
    {
       return DispatcherHelper.UIDispatcher.BeginInvoke(action);
    }
}

所以在 app.xaml.cs 中 我打电话 AppServices.Init(new DispatcherWrapper());

在单元测试中我调用 AppServices.Init(Substitute.For());

使用 NSubstitute

如果你觉得我遗漏了什么,请发表评论,我担心如何制作模拟框架来运行我以前在

中执行的操作
DispatcherHelper.UIDispatcher.Invoke

【问题讨论】:

    标签: c# wpf unit-testing mvvm mvvm-light


    【解决方案1】:

    不幸的是,最初的设计问题导致代码库难以进行单元测试。为代码创建单元测试的难度与代码设计的好坏直接相关。您在帖子中提到的文章是您需要做的事情,以使访问调度程序可模拟,因为它(调度程序)是与 UI 线程相关的实现问题,在您的单元测试期间将不可用。因此锁定Invoke

    引用你提到的文章:

    我们无法测试使用 App.Current.Dispatcher 的代码(因为 App.Current 在单元测试执行期间将是 null)。

    一个可能的解决方案是创建一个接口 IDispatcher 和一个 实现该接口的 App.Current.Dispatcher 的包装器。

    public interface IDispatcher {
        void Invoke(Action action);
        void BeginInvoke(Action action);
    }
    
    public class DispatcherWrapper : IDispatcher {
        Dispatcher dispatcher;
    
        public DispatcherWrapper() {    
            dispatcher = Application.Current.Dispatcher;        
        }
        public void Invoke(Action action) {
            dispatcher.Invoke(action);
        }
    
        public void BeginInvoke(Action action) {
            dispatcher.BeginInvoke(action);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 2010-11-09
      • 2023-03-17
      相关资源
      最近更新 更多