【问题标题】:C#/.NET: Testing BackgroundWorker with NUnitC#/.NET:使用 NUnit 测试 BackgroundWorker
【发布时间】:2009-04-15 12:27:24
【问题描述】:

当使用 NUnit 控制台运行程序运行此测试时,它会失败。如果我只用 TestDriven.NET 运行该测试,它就可以工作,但如果我用 TestDriven.NET 运行整个套件,它就不行:

[Test]
public void BackgroundWorkerFiresRunWorkerCompleted()
{
  var runner = new BackgroundWorker();
  ManualResetEvent done = new ManualResetEvent(false);
  runner.RunWorkerCompleted += delegate { done.Set(); };

  runner.RunWorkerAsync();

  bool res = done.WaitOne(TimeSpan.FromSeconds(10));
  // This assert fails:
  Assert.IsTrue(res, "RunWorkerCompleted was not executed within 10 seconds");
}

我怀疑这个问题与没有消息循环有关,但我不确定。

使用BackgroundWorker有什么要求?

是否有解决方法可以使测试正常工作?

【问题讨论】:

    标签: c# .net multithreading unit-testing backgroundworker


    【解决方案1】:

    我认为这与消息泵无关,因为无论如何测试通常都以阻塞方式运行。但可能是在“UI”线程上调用了该事件,该线程使用了未处理的 windows 消息。

    因此,如果问题是消息泵或 Windows 消息未得到处理,您可以尝试这样替换您当前的 bool res = done.WaitOne(TimeSpan.FromSeconds(10)); 行:

    DateTime end = DateTime.Now.AddSeconds(10);
    bool res = false;
    while ((!res) && (DateTime.Now<end)) {
       Application.DoEvents();
       res = done.WaitOne(0):
    }
    

    【讨论】:

    • 我们发现只有在测试(或同一测试运行中的先前测试)实例化 Windows 窗体或控件时才需要 DoEvents()。为什么?
    • 因为对于任何WinForms控件,窗口消息都需要通过消息泵传递,如果不调用DoEvents()就不会发生这种情况。
    【解决方案2】:

    您是否缺少 BGW DoWork 事件处理程序?

    【讨论】:

    • 我要测试的实际类是 BackgroundWorker 的子类并覆盖 OnDoWork()。但是,如果我添加一个 DoWork 事件处理程序,这没有什么区别。 RunWorkerCompleted 事件处理程序仍未运行。
    【解决方案3】:

    只需在你之前添加一个睡眠:

    Assert.IsTrue(res, "RunWorkerCompleted was not executed within 10 seconds");

    类似这样的:

    System.Threading.Thread.Sleep(10000);

    【讨论】:

    • 但这会使测试总是至少需要 10 秒,而通常应该在几毫秒内完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    相关资源
    最近更新 更多