2009-09-01 3 views
5

Nachdem eine Verlängerung Methode (basierend auf GUI update when starting event handler class on separate thread?) codiert:Wie testen Sie die UI-Methode beim Aufruf eines anderen Threads richtig?

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); 
    } 
} 

Ich habe diese Methode, um Unit-Test versucht, sowohl von einem UI-Thread und einem normalen Faden und ich kann nicht scheinen zu können, erreichen Das. Hier

ist die Einheit Testcode:

[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")); 
} 

der Test bestanden wird, aber wenn ich einen Haltepunkt in der InvokeEx Methode (ohne den Anruf) stelle ich sehen, daß Control.InvokeRequired falsch ist, was zu die func Methode direkt aufgerufen.

Darüber hinaus schlägt der Test fehl, weil Ergebnis nicht festgelegt ist.

Darüber hinaus während des Durchlaufens des Codes sehe ich, dass die func Methode auf dem anderen Thread (wie erwartet) und nicht auf dem Hauptthread ausgeführt wird.

Vielleicht liegt es daran, dass ich keinen echten UI-Thread habe, da ich einen Komponententest ausführe? Wie würde ich das erreichen und die ganze Botschaft pumpen?

Antwort

5

Ich habe verschiedene Dinge versucht und ich habe mit den folgenden kommen:

[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")); 
} 

perfekt Dies funktioniert jetzt.

Beachten Sie, dass ich InvokeEx für eine void-Methode eine Überladung hinzufügen musste.

Verwandte Themen