C# 单元测试控制调用问题

本文关键字:问题 调用 控制 单元测试 | 更新日期: 2023-09-27 18:32:17

我已经为WinForms应用程序编写了一个单元测试。应用在线程中执行代码,该代码在 UI 上设置结果。为此,我必须通过 Control.Invoke(delegate) 调用 UI 线程中的结果集。在应用程序中,它完美运行。在单元测试中,我必须等待异步结果。但是,在单元测试中,Control.Invoke(delegate)不会触发。

我没有线程问题。线程在单元测试中完美运行。问题是在 UI 线程上从线程调用。有没有人有提示,它是如何工作的。

为了重现此问题,我创建了一个示例 WinForms 项目和一个单元测试项目。窗体包含一个文本框和一个按钮。通过单击按钮,它会启动一个线程,等待两秒钟并在文本框中设置文本。设置文本后,它会触发一个事件。

这是 Forms 类:

public partial class TestForm : Form
{
    public TestForm()
    {
        InitializeComponent();
    }
    private void btnAction_Click(object sender, EventArgs e)
    {
        this.SetText();
    }
    public delegate void delFinish();
    public event delFinish Finish;
    public void SetText()
    {      
        Thread runner = new Thread(() => {
            Thread.Sleep(2000);
            if (this.txtResult.InvokeRequired)
                this.txtResult.Invoke((MethodInvoker)(() =>
                {
                    this.txtResult.Text = "Runner";
                    if (Finish != null)
                        Finish();
                }));
            else
            {
                this.txtResult.Text = "Runner";
                if (Finish != null)
                    Finish();
            }
        });
        runner.Start();
    }
}

这是单元测试:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        ManualResetEvent finished = new ManualResetEvent(false);  
        TestForm form = new TestForm();
        form.Finish += () => {
            finished.Set();
        };
        form.SetText();
        Assert.IsTrue(finished.WaitOne());
        Assert.IsTrue(!string.IsNullOrEmpty(form.txtResult.Text));
    }
}

问题是这一行不会执行:

              this.txtResult.Invoke((MethodInvoker)(() =>

感谢您的任何帮助!

C# 单元测试控制调用问题

问题是,在上面的示例中,当前线程被阻止,但控件想要在此线程上调用。

解决方案是将其他事件 Application.DoEvents() 并生成执行到另一个线程 Thread.Yield()。

测试方法如下所示:

    [TestMethod]
    public void TestMethod1()
    {
        bool finished = false;
        TestForm form = new TestForm();
        form.Finish += () =>
        {
            finished = true;
        };
        form.SetText();
        while (!finished)
        {
            Application.DoEvents();
            Thread.Yield();
        }                         
        Assert.IsTrue(!string.IsNullOrEmpty(form.txtResult.Text));
    }

希望这对某人有帮助。