【问题标题】:Mocking a C# timer with Moq使用 Moq 模拟 C# 计时器
【发布时间】:2012-10-22 19:01:03
【问题描述】:

我正在尝试创建一个 WPF MVVM 视图模型,该模型具有注入 System.Timing.Timer 的依赖项,并希望使用 Moq 测试该视图模型。

我围绕Timer 类编写了一个薄包装器,它有一个接口ITimer,但我不确定真正测试计时器对类的贡献的最佳方法。有没有一种“强制”模拟已过事件的好方法?其他人有更好的技术吗?

【问题讨论】:

  • 看看这个question和这个question
  • 谢谢,我在谷歌上搜索了一些类似的东西,但我的查询主要集中在一般事件而不是计时器上,并且找不到很多好的结果。

标签: c# unit-testing moq


【解决方案1】:

您应该在isolation 中测试您的代码。否则,您不知道您的代码是否按预期运行,或者外部依赖是否存在一些副作用。因此,为外部资源(配置文件、计时器等)创建可模拟的包装器是将 SUT 与外部代码分开的唯一方法。

【讨论】:

  • 我对隔离的概念了如指掌,因此我在Timer 周围写了一个可模拟的锡包装。我对专门模拟事件的技术更感兴趣。看来Ufuk的评论正是我要找的。​​span>
  • 引发事件只是通过模拟在模型上调用一些操作。我看不出有什么奇怪的地方。
【解决方案2】:

您可以使用像Moq 这样的框架来触发事件。你也可以像这样创建一个FakeTimer

public class FakeTimer : IMyTimer
{
    private event ElapsedEventHandler elaspedHandler;
    private bool _enabled;

    public void Dispose() => throw new NotImplementedException();

    public FakeTimer(ElapsedEventHandler elapsedHandlerWhenTimeFinished, bool startImmediately)
    {
        this.elaspedHandler = elapsedHandlerWhenTimeFinished;
        _enabled = startImmediately;
    }

    public void Start() => _enabled = true;
    public void Stop() => _enabled = false;
    public void Reset() => _enabled = true;

    internal void TimeElapsed()
    {
        if (this._enabled)
            elaspedHandler.Invoke(this, new EventArgs() as ElapsedEventArgs);
    }
}

TimeElapsed() 是您在单元测试中调用的名称,表示时间已过。

然后它将调用与之关联的事件。

在下面的示例中,MyCallBackMethod 将在 fakeTimer.TimeElapsed() 上调用
var fakeTimer = new FakeTimer(350, MyCallBackMethod, false)

【讨论】:

    猜你喜欢
    • 2018-10-22
    • 2015-11-11
    • 2013-12-23
    • 1970-01-01
    • 2011-06-13
    • 2019-09-11
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多