2009-09-01 15 views
5

Po kodowane metodę rozszerzenia (w oparciu o GUI update when starting event handler class on separate thread?):Jak poprawnie testować urządzenie wywołując metodę interfejsu użytkownika na innym wątku?

public static class ControlExtensions 
{ 
    public static TResult InvokeEx<TControl, TResult> (this TControl control, 
                 Func<TControl, TResult> func) 
     where TControl : Control 
    { 
     if (control.InvokeRequired) 
      return (TResult)control.Invoke (func, control); 

     return func (control); 
    } 
} 

Próbowałem do testów jednostkowych tej metody zarówno z wątku UI i normalny gwint i nie wydaje się być w stanie osiągnąć że.

Oto kod testowy jednostka:

[Test] 
public void TestInvokeExWithMethodReturningResultOnOtherThread() 
{ 
    // Prepare 
    string result = string.Empty; 
    var form = new Form(); 
    var thread = new Thread (() => 
          { 
           result = form.InvokeEx (f => f.Text); 
          }); 

    // Execute 
    thread.Start(); 
    thread.Join (1000); 

    // Verify 
    Assert.That (result, Is.EqualTo ("Some label")); 
} 

Przejścia testów ale jeśli ustawienie przerwania w InvokeEx metody (połączenia) nie widzę Control.InvokeRequired fałszywe powodując bezpośrednio wywoływana metoda func.

Co więcej, teraz test kończy się niepowodzeniem, ponieważ wynik nie jest ustawiony. Dodatkowo, podczas przechodzenia przez kod widzę, że metoda func jest wykonywana na drugim wątku (zgodnie z oczekiwaniami), a nie na głównym wątku.

Może to dlatego, że nie mam prawdziwego wątku interfejsu użytkownika, ponieważ wykonuję test jednostkowy? Jak to osiągnąć i całą pompę wiadomości?

Odpowiedz

5

Próbowałem różnych rzeczy i mam wymyślić, co następuje:

[Test] 
public void TestInvokeExWithMethodReturningResultOnOtherThread() 
{ 
    // Prepare 
    string result = string.Empty; 
    var form = new Form(); 
    var uiThread = new Thread (() => Application.Run (form)); 
    uiThread.SetApartmentState (ApartmentState.STA); 
    uiThread.Start(); 
    Thread.Sleep (100); 
    var thread = new Thread (() => result = form.InvokeEx (f => f.Text)); 

    // Execute 
    thread.Start(); 
    thread.Join(); 
    form.InvokeEx (f => f.Close()); 
    uiThread.Join(); 

    // Verify 
    Assert.That (result, Is.EqualTo ("Some label")); 
} 

to teraz działa idealnie.

Zauważ, że musiałem dodać przeciążenie dla InvokeEx dla metody void.

Powiązane problemy