.net - 如何在另一个线程上正确地对调用 UI 方法进行单元测试?

标签 .net multithreading unit-testing c#-3.0 nunit

编写了一个扩展方法(基于 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 为假导致 功能 方法直接调用。

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

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

也许是因为我在执行单元测试后没有真正的 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 添加重载。

关于.net - 如何在另一个线程上正确地对调用 UI 方法进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1362858/

相关文章:

multithreading - 将数据从线程发送到主 VCL 线程

python - 将 Mock() 传递到 blinker signal.connect() 引发 "AttributeError: __name__"

c# - 从 MS Access 转换 OLE 图像对象以在 .NET 中使用

c++ - 包含另一个关键部分的关键部分?

c# - wp7能力检测.exe

java - 避免线程在更改 Activity 时重新启动

php - 测试遗留 PHP 意大利面条代码?

python - 在单元测试中模拟 python 装饰器

c# - MonoGame - BlendState - 2D SpriteBatch

c# - 有没有更简单的方法将多个 if/else 语句相互写入?