.net – 如何在另一个线程上正确单元测试调用UI方法?

编写了扩展方法(基于GUI update when starting event handler class on separate 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);
    }
}

我一直试图从UI线程和普通线程单元测试这个方法,我似乎无法实现这一点.

这是单元测试代码:

[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为false,导致直接调用func方法.

此外,现在测试失败,因为未设置结果.

另外,在逐步执行代码时,我看到func方法在另一个线程上执行(如预期的那样),而不是在主线程上执行.

也许是因为我执行单元测试后没有真正的UI线程?我将如何实现这一点以及所有消息?

最佳答案
我一直在尝试不同的东西,我想出了以下内容:

[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方法的重载.

转载注明原文:.net – 如何在另一个线程上正确单元测试调用UI方法? - 代码日志