2009-09-01 9 views
5

Dopo aver codificato un metodo di estensione (sulla base di GUI update when starting event handler class on separate thread?):Come testare correttamente il metodo di chiamata dell'interfaccia utente su un altro thread?

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

Ho cercato di unità di prova questo metodo sia da un thread dell'interfaccia utente e un filo normale e io non riesco a essere in grado di raggiungere quella.

Ecco il codice di prova unità:

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

I test viene superato ma se Ho impostato un punto di interruzione nel InvokeEx metodo (non il call) vedo che Control.InvokeRequired è falso conseguente il metodo func chiamato direttamente.

Inoltre, ora il test non riesce perché il risultato non è impostato.

Inoltre, durante l'esecuzione del codice, vedo che il metodo viene eseguito sull'altro thread (come previsto) e non sul thread principale.

Forse è perché non ho un vero thread UI dal momento che sto eseguendo un test unitario? Come potrei ottenere quello e tutto il messaggio che pompa?

risposta

5

Ho provato cose diverse e mi è venuta in mente la seguente:

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

Questo ora funziona perfettamente.

Nota che ho dovuto aggiungere un sovraccarico per InvokeEx per un metodo di annullamento.

Problemi correlati