I’m building a timer class but I can’t make a test pass. I want to test that a method is called when the time on the timer is elapsed.
I have the following class:
public class TimeOutTimer
{
private readonly ISubscriber _subscriber;
private Timer _timer;
public TimeOutTimer(ISubscriber subscriber)
{
_subscriber = subscriber;
}
public void Start()
{
_timer = new Timer(1000);
_timer.Start();
_timer.Elapsed += TimerOnElapsed;
}
private void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
{
_subscriber.TimeReached();
}
}
And the test, using Moq:
[Test]
public void Start_WithValidParameters_TriggersTimeReached()
{
var subscriberMock = new Mock<ISubscriber>();
var timer = new TimeOutTimer(subscriberMock.Object);
timer.Start();
subscriberMock.Verify(subscriber => subscriber.TimeReached());
}
If I take the Timer out and make a direct call to _subscriber.TimeReached(), it works.
Am I doing something wrong?
In your example the event should be invoked after 1000ms, whereas you verify straight away. Clearly the event cannot be invoked at that point.
The easy way out is to put a thread sleep in your test.
However this is not really the correct way to generate a unit test for a time based class.
The correct way would be to create an
ITimerinterface which is then implemented by an adapter based onTimer.The the
ITimerthen becomes a dependency ofTimeoutTimer, and is passed to it in the constructor or as a property.In your test you can then Mock the timer so it synchronises with your test without waiting (e.g. by being able to manually trigger the event by controlling the class).