.NET中的单元测试System.Threading.Timer

Gha*_*han 11 .net multithreading asynchronous timer

如何基于.NET中的System.Threading.Timer对计时器进行单元测试System.Threading.Timer有一个回调方法

Aar*_*ght 10

您可以通过不实际创建直接依赖来对其进行单元测试System.Threading.Timer.相反,创建一个ITimer接口,并System.Threading.Timer实现它的包装器.

首先,您需要将回调转换为事件,以便它可以成为接口的一部分:

public delegate void TimerEventHandler(object sender, TimerEventArgs e);

public class TimerEventArgs : EventArgs
{
    public TimerEventArgs(object state)
    {
        this.State = state;
    }

    public object State { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

然后创建一个接口:

public interface ITimer
{
    void Change(TimeSpan dueTime, TimeSpan period);
    event TimerEventHandler Tick;
}
Run Code Online (Sandbox Code Playgroud)

包装材料:

public class ThreadingTimer : ITimer, IDisposable
{
    private Timer timer;

    public ThreadingTimer(object state, TimeSpan dueTime, TimeSpan period)
    {
        timer = new Timer(TimerCallback, state, dueTime, period);
    }

    public void Change(TimeSpan dueTime, TimeSpan period)
    {
        timer.Change(dueTime, period);
    }

    public void Dispose()
    {
        timer.Dispose();
    }

    private void TimerCallback(object state)
    {
        EventHandler tick = Tick;
        if (tick != null)
            tick(this, new TimerEventArgs(state));
    }

    public event TimerEventHandler Tick;
}
Run Code Online (Sandbox Code Playgroud)

显然你会添加Change你需要使用的构造函数和/或方法的任何重载Threading.Timer.现在你可以根据ITimer假计时器对任何东西进行单元测试:

public class FakeTimer : ITimer
{
    private object state;

    public FakeTimer(object state)
    {
        this.state = state;
    }

    public void Change(TimeSpan dueTime, TimeSpan period)
    {
        // Do nothing
    }

    public void RaiseTickEvent()
    {
        EventHandler tick = Tick;
        if (tick != null)
            tick(this, new TimerEventArgs(state));
    }

    public event TimerEventHandler Tick;
}
Run Code Online (Sandbox Code Playgroud)

无论何时你想模拟一个刻度线,只需要RaiseTickEvent打假.

[TestMethod]
public void Component_should_respond_to_tick
{
    ITimer timer = new FakeTimer(someState);
    MyClass c = new MyClass(timer);
    timer.RaiseTickEvent();
    Assert.AreEqual(true, c.TickOccurred);
}
Run Code Online (Sandbox Code Playgroud)