Читать книгу Dojos für Entwickler 2 - Stefan Lieser - Страница 50
Listing 4 Besser : WaitHandle.
Оглавление[TestFixture] public class AsynchronizerTests { private EventWaitHandle waitHandle; private Asynchronizer<int> sut; [SetUp] public void Setup() { sut = new Asynchronizer<int>(); waitHandle = new EventWaitHandle( false, EventResetMode.ManualReset); } [Test] public void Result_event_is _raised_with_parameter() { var result = 0; sut.Result += x => { result = x; waitHandle.Set(); }; sut.Process(42); Assert.That(waitHandle.WaitOne(500), Is.True); Assert.That(result, Is.EqualTo(42)); } }
Das WaitHandle wird verwendet, um nach Aufruf der Process-Methode darauf zu warten, dass der Result-Event auf dem neu gestarteten Thread seine Arbeit verrichtet hat. Das WaitHandle befindet sich anfangs im Zustand „nicht gesetzt“. Wird waitHandle.WaitOne aufgerufen, wird der aktuelle Thread so lange angehalten, bis das WaitHandle gesetzt ist. Daher muss das WaitHandle im Result-Event mit Set gesetzt werden. Auf diese Weise wacht der Thread, auf dem der Test läuft, dann wieder auf und kann sein Assert ausführen.
Damit der Test bei einem Fehler nicht unendlich lange wartet, habe ich bei WaitOne einen Timeout von 500 ms definiert. Dadurch wird das WaitHandle entweder durch Set innerhalb von 500 ms gesetzt oder durch einen Timeout. Der Timeout tritt automatisch ein, wenn das WaitHandle nicht nach der hinterlegten Zeit mit Set gesetzt wird, in diesem Fall nach 500 ms. Der Timeout wird dadurch signalisiert, dass WaitOne false zurückliefert.
Um den Timeout im Test zu erkennen, habe ich ein Assert ergänzt, welches prüft, ob WaitOne mit true beendet wurde. Wenn das der Fall ist, ist das WaitHandle ordnungsgemäß mit Set gesetzt worden, sprich, der Result-Event wurde ausgelöst. Liefert WaitOne jedoch false zurück, ist im Test etwas schiefgelaufen, weil das WaitHandle durch einen Timeout ausgelöst wurde.
Hier ist es nun tatsächlich angemessen, darüber nachzudenken, ob 500 ms als Timeout ausreichend sind. Auf einem Continuous Integration Server kann das schon mal knapp bemessen sein. Da die Timeout-Zeitspanne nur dann in Anspruch genommen wird, wenn etwas schiefläuft, können Sie den Timeout nun ohne Not auf mehrere Sekunden hochsetzen. Solange alles in Ordnung ist, und das sollte der Normalfall sein, läuft der Test dann durch, so schnell es eben geht. Nur für den hoffentlich seltenen Fall, dass jemand den Code „kaputt gemacht hat“, tritt die Timeout-Wartezeit in Kraft.