【问题标题】:unit testing MVVMLight DispatcherHelper with Timer does not work使用 Timer 进行单元测试 MVVMLight DispatcherHelper 不起作用
【发布时间】:2016-04-18 20:34:29
【问题描述】:

我有一个使用 System.Threading.Timer 的应用程序。当调用 Timer 回调时,我必须在 UI 线程上做一些事情。我使用 MVVMLight DispatcherHelper 来做到这一点。当我运行应用程序时它工作正常,但是当我对它进行单元测试(使用 nUnit)时,DispatcherHelper 不会调用 Action。

为了演示它,我创建了一个简单的单元测试

Timer _Timer; //this is System.Threading.Timer
bool _DispatcherWorks;

[Test]
public async Task MVVMDispatcherTest()
{
     DispatcherHelper.Initialize();
     Assert.That(DispatcherHelper.UIDispatcher, Is.Not.Null);

     _Timer = new Timer(timerCallback, null, 500, 500); //start timer in 0.5 seconds and run every 0.5 seconds

     Thread.Sleep(2000); //wait for timer to tick

     Assert.That(_DispatcherWorks, Is.True); //will fail
}

private void timerCallback(object state)
{
     Console.WriteLine("Timer tick");
     Assert.That(DispatcherHelper.UIDispatcher, Is.Not.Null);
     DispatcherHelper.CheckBeginInvokeOnUI(() =>
     {
         _DispatcherWorks = true; //this is never called
     });
 }

我的计时器被执行了 3 次,这是预期的。但是 DispatcherHelper.CheckBeginInvoikeOnUI 中的 Action 不会被调用。谁能建议为什么这不起作用以及如何使其可测试?

【问题讨论】:

    标签: c# multithreading unit-testing timer mvvm-light


    【解决方案1】:

    您的 _Timer 是 System.Threading.Timer 的一个实例(将此实例称为 timerA)。在您的 Dispatchhelper 中创建了一个新的 System.Threading.Timer 实例(调用该实例 timerB)。这应该可以解释为什么您的测试不起作用。 为了使其可测试,您可以做一些事情。您可以在 Dispatch-helper 中注入计时器,但您必须更改您的生产代码以适应测试。如果可以帮助,我通常会反对。

    您还可以使用 Microsoft Fakes 来模拟 System.Threading.Timer。这是我会采取的方法。

    【讨论】:

      【解决方案2】:

      感谢您的建议,但这对我不起作用,因为我实际上想测试计时器事件在它过去时发生了什么。所以这就是我所做的。

      1. 我从 MVVMLight DispatcherHelper.cs 中获取源代码,将这个类从静态类转换为非静态类,并从中提取接口。我将 Dispatcher 作为参数传递给构造函数。在我的 ViewModelLocator 中,我启动了新的 DispatcherHelper 类。
      2. 我将在 ViewModelLocator 中启动的同一个 DispatcherHelper 对象传递给每个需要 Dispatcher 的 ViewModel 的构造函数。然后我在计时器经过的事件中使用这个对象。
      3. 在我的单元测试中,我使用 nSubstitute 来模拟 IDispatcherHelper 接口并重新定义 CheckBeginInvokeOnUI 方法以简单地执行传递的操作而不是使用 Dispatcher。
      4. 现在,当我测试我的 ViewModel 时,我将这个模拟的 DispatcherHelper 传递给 ViewModel 构造函数,并且我能够测试计时器内部发生的情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-09
        相关资源
        最近更新 更多