Jak testować stoper oparciu o System.Threading.Timer w .NET System.Threading.Timer jednostka ma metodę zwrotnąjednostka testowa System.Threading.Timer w .NET
Odpowiedz
Możesz go przetestować, nie tworząc bezpośredniej zależności od System.Threading.Timer
. Zamiast tego utwórz interfejs ITimer
i otoki o wartości System.Threading.Timer
, który go implementuje.
Najpierw trzeba przekształcić zwrotnego do wydarzenia, tak aby mógł on być częścią interfejsu:
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; }
}
następnie utworzyć interfejs:
public interface ITimer
{
void Change(TimeSpan dueTime, TimeSpan period);
event TimerEventHandler Tick;
}
oraz owijkę:
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;
}
Oczywiście należy dodać wszelkie przeciążenia konstruktora i/lubMetoda 0, której należy użyć od Threading.Timer
. Teraz można przetestować urządzenie wszystko w zależności od ITimer
z fałszywą czasowy:
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;
}
Ilekroć chcesz symulować kleszcza, zadzwoń RaiseTickEvent
na fałszywe.
będę testować go w w taki sam sposób jak w każdej innej klasie, ale z krótkimi przerwami, aby uniknąć długiego testu urządzenia. Innym podejściem jest testowanie własnego kodu i używanie próbnego licznika czasu (np. NMock), ale to zależy od tego, jak wygląda twój kod. Czy możesz opublikować niektóre fragmenty kodu?
Jeśli czas po prostu zmienia metodę wywołania zwrotnego, wystarczy sprawdzić poprawność tej metody, a nie czas działania systemu.
Poza tym zalecam używanie MultimediaTimer zamiast - jest o wiele bardziej dokładny.
Powiedz, że chcę zegar, który odpala raz na godzinę. Czy polecasz 'MultimediaTimer' dla każdego? :) –
Tak, i połącz go z Dispatcherem .NET, jeśli chcesz zwrócić wątek interfejsu użytkownika. –
Mam nadzieję, że cokolwiek ta funkcja stanowi większą część, pozwala skonfigurować interwał czasomierza. Powinieneś być w stanie użyć tego interfejsu, aby wstrzyknąć krótki odstęp odpowiedni do testowania jednostkowego. Mam pytanie o wartość tego testu: Czy testujesz interwał (bezcelowy) lub czy rutyna jest tak często wywoływana co jakiś czas?
To wygląda dobrze, ale dlaczego tworzysz własnego delegata, a nie tylko używasz delegata TimerCallback z BCL? – Shaun
@Shaun: Ponieważ ten delegat nie jest prawidłową obsługą zdarzeń. Program obsługi zdarzeń ma określony podpis: 'obiekt nadawca, TEventArgs e', gdzie' TEventArgs: EventArgs'. – Aaronaught
Uważam, że w dzisiejszych czasach, gdy zamknięcia są tak chętnie wspierane, jeśli chciałem czegoś szybkiego i brudnego, nie wiem, czy zawracałbym sobie głowę całą deklaracją zdarzenia i okablowaniem, mógłbym po prostu przekazać akcję zamiast tego. – Aaronaught