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

时间:2014-11-28 10:13:09

标签: c# unit-testing

我已经为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)(() =>

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

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

解决方案是将其他事件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));
    }

希望这对某人有帮助。