什么阻止你包装这个?
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;
}
}
在测试中,我们强制计时器在需要时加注,并且我们检查TimerElapsedHandler中的代码是否通过置位ReceivedEvent属性来执行.实际上,这种方法可能会做得更多,但这只会改变我们做断言的方式 – 想法保持不变.
编辑:您还可以尝试使用Moles,该框架允许您生成任何框架类型/方法的假冒.但是,如果你想要嘲笑计时器,我会采用包装方式.