unit testing系统.timers.timer

我一直在阅读有关定时器和线程的unit testing的问题。 我找到了关于unit testingsystem.threading.timers的SO问题,但是我需要对system.timers.timer和包装类进行unit testing,这对于这个问题似乎并不顺利。

我只需要知道如何模拟计时器和/或系统时间,以便对它进行unit testing。 我似乎无法在谷歌的任何地方找到这个。

编辑和更新:有意义的是,如果我通过如下包装来提取计时器,我可以生成一个计时器并使用模拟将其替换为不同的计时器。 然后,相关部分将采用我在运行时注入的计时器(原始而不是模拟)并测试它已过去的事件代码。

什么阻止你包装这个?

public interface ITimer { void Start(double interval); void Stop(); event ElapsedEventHandler Elapsed; } 

这几乎是你所有的界面需求。 让我们看看这是怎么回事(请注意,你当然可以暴露更多的Timer属性,但这是非常基本的东西应该足够了):

 public class MyTimer : ITimer { private Timer timer = new Timer(); public void Start(double interval) { timer.Interval = interval; timer.Start(); } public void Stop() { timer.Stop(); } public event ElapsedEventHandler Elapsed { add { this.timer.Elapsed += value; } remove { this.timer.Elapsed -= value; } } } 

现在,您将如何在测试中使用它(假设我们使用FakeItEasy作为选择的模拟框架):

 var timerFake = A.Fake(); var classUnderTest = new MyClass(timerFake); // tell fake object to raise event now timerFake.Elapsed += Raise.With(ElapsedEventArgs.Empty).Now; // assert whatever was supposed to happen as event response, indeed did Assert.That(classUnderTest.ReceivedEvent, Is.True); 

上面的示例实际上测试了一旦定时器上的事件被引发时发生的代码。 考虑MyClass看起来像这样:

 public class MyClass { private ITimer timer; public MyClass(ITimer timer) { this.timer = timer; this.timer.Elapsed += TimerElapsedHandler; } public bool ReceivedEvent { get; set; } private void TimerElapsedHandler(object sender, ElapsedEventArgs e) { ReceivedEvent = true; } } 

在测试中,我们强制计时器在需要时加注,我们通过声明ReceivedEvent属性设置来检查TimerElapsedHandler代码是否TimerElapsedHandler执行。 实际上,这种方法可能会做得更多,但这只会改变我们做断言的方式 – 想法保持不变。


编辑:你也可以尝试Moles ,这个框架允许你生成任何框架类型/方法的假货 。 但是,如果你想要的是模拟计时器,我会采用包装方法。

您需要测试计时器或测试每个事件中执行的代码吗? 如果是这样,您可以将该逻辑放在另一个类中,然后测试它。 你可以相信计时器会调用它…