什么阻止你包装这一个?
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<ITimer>();
var classUnderTest = new MyClass(timerFake);
// tell fake object to raise event now
timerFake.Elapsed += Raise.With<ElapsedEventArgs>(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,一个框架,让你产生假货任何框架类型/方法。但是,如果嘲笑定时器是你想要的,我会采用包装方法。
很难提出建议,因为你没有提供任何关于你想要覆盖哪个测试用例和哪个代码块代表测试用例下的逻辑的任何信息。 – sll 2012-01-31 23:09:47
您需要测试计时器或测试每个事件中执行的代码吗?如果是这样,你可以把这个逻辑放到另一个类中去测试。你可以相信定时器调用它。 – ivowiblo 2012-01-31 23:22:55
@ivowiblo:我不知道如何将您的评论标记为答案,但我认为这与我能找到的问题的实际答案最接近。 – deltree 2012-01-31 23:35:38