Chris Covert
Chris Covert

Reputation: 2834

Mocking a C# timer with Moq

I'm attempting to create a WPF MVVM View Model that has a dependency injected System.Timing.Timer, and wish to test the view model with Moq.

I wrote a thin wrapper around the Timer class that has a interface ITimer, but am unsure of the best way to really test the timer's contribution to the class. Is there a good way to 'force' a mock elapsed event? Does somebody else have a better technique?

Upvotes: 8

Views: 3383

Answers (2)

thalacker
thalacker

Reputation: 2827

You could use a framework like Moq to trigger the event. You could also create a FakeTimer like so:

public class FakeTimer : IMyTimer
{
    private event ElapsedEventHandler elaspedHandler;
    private bool _enabled;

    public void Dispose() => throw new NotImplementedException();

    public FakeTimer(ElapsedEventHandler elapsedHandlerWhenTimeFinished, bool startImmediately)
    {
        this.elaspedHandler = elapsedHandlerWhenTimeFinished;
        _enabled = startImmediately;
    }

    public void Start() => _enabled = true;
    public void Stop() => _enabled = false;
    public void Reset() => _enabled = true;

    internal void TimeElapsed()
    {
        if (this._enabled)
            elaspedHandler.Invoke(this, new EventArgs() as ElapsedEventArgs);
    }
}

Where TimeElapsed() is what you would call in your unit tests to indicate that the time has passed.

It will then call off to the event associated with it.

In this example below, MyCallBackMethod would be called on fakeTimer.TimeElapsed()
var fakeTimer = new FakeTimer(350, MyCallBackMethod, false)

Upvotes: 0

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236208

You should test your code in isolation. Otherwise you don't know whether your code behaves as expected, or there is some side-effect in external dependency. Thus creating mockable wrappers for external resources (configuration files, timers, etc) is the only way you can separate your SUT from external code.

Upvotes: 3

Related Questions