2009-09-01 4 views
5

Habiendo codificado un método de extensión (basado en GUI update when starting event handler class on separate thread?):¿Cómo unitar correctamente el método de UI de llamada de prueba en otro hilo?

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

que he estado tratando de unidad de prueba de este método, tanto desde un hilo de interfaz de usuario y un hilo normal y me parece que no puede ser capaz de lograr ese.

Este es el código de prueba de unidad:

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

Los pases de ensayo, pero si fijo un punto de interrupción en el InvokeEx método (no la llamada) veo que Control.InvokeRequired es falso que resulta en el func método llamado directamente.

Además, ahora la prueba falla porque el resultado no está configurado.

Además, al pasar por el código, veo que el método func se ejecuta en el otro subproceso (como se esperaba) y no en el subproceso principal.

Tal vez es porque no tengo un hilo de UI real ya que estoy ejecutando una prueba de unidad? ¿Cómo podría lograr eso y todo el bombeo del mensaje?

Respuesta

5

he estado tratando cosas diferentes y yo he llegado con lo siguiente:

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

Esto ahora funciona perfectamente.

Tenga en cuenta que tuve que agregar una sobrecarga para InvokeEx para un método nulo.

Cuestiones relacionadas