2010-03-02 11 views

Odpowiedz

9

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.

+0

To wygląda dobrze, ale dlaczego tworzysz własnego delegata, a nie tylko używasz delegata TimerCallback z BCL? – Shaun

+1

@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

+0

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

1

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?

0

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.

+0

Powiedz, że chcę zegar, który odpala raz na godzinę. Czy polecasz 'MultimediaTimer' dla każdego? :) –

+0

Tak, i połącz go z Dispatcherem .NET, jeśli chcesz zwrócić wątek interfejsu użytkownika. –

0

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?

Powiązane problemy