I've been reading over the questions about unit testing with timers and threading. I found the SO question about unit testing system.threading.timers, but I need to unit test a system.timers.timer and a wrapper class doesn't seem to work quite as smoothly for this one.
I just need to know how to mock the timer and/or system time in order to unit test against it. I can't seem to find this anywhere on google.
edit & update: It makes sense that if I extract the timer by wrapping it as below, I can generate a timer and use mocking to replace it with a different timer. The relevant part is then to take that timer that I'm injecting at runtime (the original, not a mock) and test it's elapsed event code.
What stops you from wrapping this one?
public interface ITimer
{
void Start(double interval);
void Stop();
event ElapsedEventHandler Elapsed;
}
That's pretty much all your interface needs. Let's see how this could go (note that you could of course expose more Timer
properties, but that's pretty much basic stuff that should be enough):
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; }
}
}
Now, how would you utilize this in your testing (assuming we're using FakeItEasy as mocking framework of choice):
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);
Example above actually does test the code that happens once the event on timer is raised. Consider MyClass
looking like this:
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;
}
}
In the test, we force timer to raise when we need it, and we check whether code in TimerElapsedHandler
executed, by asserting ReceivedEvent
property was set. In reality, this method might do more than that, but that will only change the way we do assertions - idea remains the same.
Edit: You can also try Moles, a framework that allows you to generate fakes of any framework types/methods. However, if mocking timer was all you wanted, I'd go with wrapper approach.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With