C # Unit test call contol invoke

I wrote a unit test for a WinForms application. The application runs code on a thread that sets the result to the UI. To do this, I have to call the result set on the UI thread Control.Invoke(delegate)

. It works fine in the app. In a unit test, I need to wait for the async result. But in the unit test it Control.Invoke(delegate)

doesn't work.

I have no problem with threads. Threads work fine in unit test. The problem is calling on the thread UI thread. Does anyone have a hint how this works.

To reproduce this problem, I created a sample WinForms project and a unit test project. The form contains a text box and a button. By clicking on the button, it will start the stream, wait two seconds and set the text in the text box. After setting the text, it raises the event.

This is the Forms class:

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

      

This is a unit test:

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

      

The problem is that this line won't execute:

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

      

Thanks for any help!

+3


source to share


1 answer


The problem is that in the example above, the current thread is blocking, but on that thread, the control wants to be called.

The solution lies in other Application.DoEvents () events and execution for another thread, Thread.Yield ().

The testing method looks like this:



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

      

Hope this helps someone.

0


source







All Articles