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 ,这个框架允许你生成任何框架类型/方法的假货 。 但是,如果你想要的是模拟计时器,我会采用包装方法。
您需要测试计时器或测试每个事件中执行的代码吗? 如果是这样,您可以将该逻辑放在另一个类中,然后测试它。 你可以相信计时器会调用它…