1

我们尝试对一些旧的遗留代码进行自动化测试。有一个表单可以打开,运行计时器并从端口读取数据。unittest 打开表单,但计时器不会滴答,直到 Application.DoEvents 启动进程处理 windows 消息队列。它是不同的,因为它是从 unittest 执行的,而 Application.Run 不是代码的一部分。

但是我们不能通过 Application.DoEvents 阻塞 unittest 线程,因为我们需要通过 assert 等待和检查数据。

ThreadPool.QueueUserWorkItem(x =>
{
    While(!form.workFinished)
    { 
         Application.DoEvents();
         Thread.Sleep(50);
    }
    synchronization.Set();
});
synchronization.WaitOne();

Assert.AreEqual(10000, form.recorded.Count);

但是这个片段并没有达到我的预期。它与从 WinForm App 执行表单不同吗?我可以从线程池调用 Application.DoEvents 吗?

我真的不想真的不修改遗留代码。我只需要让单元测试在当前解决方案上工作。

4

1 回答 1

2

最好的方法是使用 Application.Run 正常运行表单。测试完成后,关闭表单或在该线程上调用 Application.Exit 。

DoEvents在当前线程上泵送事件。可以有多个 UI 线程。DoEvents只影响当前的。

您的单元测试代码可能如下所示:

Form form = null;
var task = Task.Factory.StartNew(() => {
 form = new Form(); //Run ctor on UI thread.
 Application.Run(form);
}, LongRunning);

//Work with the form here.

form.Invoke(() => Application.Exit());
task.Wait();

这只是一个草图。缺少同步,我相信还有其他事情要解决。

LongRunning确保 GUI 每次都在新线程上运行。这可以防止从测试到测试的状态泄漏。

基本上,这是标准的 UI 线程加工作线程模型。这里,单元测试线程是worker,需要创建UI线程。通常,UI 线程将是Main线程,并且将创建工作线程。

于 2015-12-07T15:34:40.087 回答