2009-09-01 4 views
5

После закодирован метода расширения (на основе GUI update when starting event handler class on separate thread?):Как правильно протестировать метод вызова UI в другом потоке?

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

Я пытался модульное тестирование этого метода как из потока пользовательского интерфейса и нормальная нить, и я не могу показаться, чтобы быть в состоянии достичь что.

Здесь блок тестового код:

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

тест пройдены, но если я установить контрольную точку в InvokeEx метода (а не вызов) Я вижу, что Control.InvokeRequired ложно в результате чего func метод, называемый напрямую.

Кроме того, теперь тест не проходит, потому что результат не установлен.

Кроме того, выполняя код, я вижу, что метод func выполняется на другом потоке (как и ожидалось), а не на основном потоке.

Возможно, это потому, что у меня нет реального потока пользовательского интерфейса, так как я выполняю единичный тест? Как я могу это сделать и все сообщения перекачать?

ответ

5

Я пытался разные вещи, и я придумал следующее:

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

Это теперь работает отлично.

Обратите внимание, что мне пришлось добавить перегрузку для InvokeEx для метода void.

Смежные вопросы