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 t
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.
You need to test the timer or test the code executed in each event? If so, you can put that logic in another class and just test that. You can trust the timer will call it...