Модульный тест System.Threading.Timer в.NET
Как выполнить модульное тестирование таймера на основе System.Threading.Timer в.NET В System.Threading.Timer есть метод обратного вызова
4 ответа
Вы можете протестировать его, не создавая прямую зависимость от 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; }
}
Затем создайте интерфейс:
public interface ITimer
{
void Change(TimeSpan dueTime, TimeSpan period);
event TimerEventHandler Tick;
}
И обертка:
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;
}
Очевидно, вы бы добавили любые перегрузки конструктора и / или 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;
}
Всякий раз, когда вы хотите имитировать тик, просто позвоните 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);
}
Я протестирую его так же, как и любой другой класс, но с короткими временными интервалами, чтобы избежать длительного выполнения модульного теста. Другой подход заключается в тестировании только вашего собственного кода и использовании ложного таймера (например, NMock), но это зависит от дизайна вашего кода. Можете ли вы опубликовать некоторые фрагменты кода?
Надеемся, что независимо от того, является ли эта функция большей частью, можно настроить интервал таймера. Вы должны иметь возможность использовать этот интерфейс для ввода короткого интервала, подходящего для модульного тестирования. У меня есть вопрос о значении этого теста: тестируете ли вы интервал (бессмысленно) или что процедура фактически вызывается примерно так часто?
Если время просто меняет метод обратного вызова, тогда вам просто нужно проверить правильность этого метода, а не то, как работает системное время.
Кроме того, я рекомендую использовать вместо этого MultimediaTimer - он намного точнее.