首页 > 解决方案 > 如何在测试方法上触发 AutoResetEvent 等待句柄?

问题描述

在 C# 中的自动化测试 (MSTest) 中工作时,测试方法从外部库调用方法,然后它必须等到触发事件,发出操作完成的信号。

我正在尝试使用本文中描述的方法:

[Test]
public void TestEventualEventTimesOut() {
  AutoResetEvent _autoResetEvent = new AutoResetEvent(false);
  var actual = string.Empty;

  var aClass = new AClass();
  aClass.SomethingHappened += (_, s) => { actual = s; _autoResetEvent.Set(); };

  aClass.DoSomethingThatFiresAnEventEventually("A");


  Assert.IsFalse(_autoResetEvent.WaitOne());
  Assert.AreEqual("", actual);
}

问题是“SomethingHappened”从未被解雇。

例如,如果从 Windows 窗体应用程序而不是测试方法调用此方法,我验证了该事件是否正确触发。

“DoSomethingThatFiresAnEventEventually”方法在内部也调用了一些方法,稍后将触发一些事件,最终将触发SomethingHappened事件。

我还尝试使用此线程中的 TaskCompletionSource 策略,但行为没有改变。

我试图理解为什么这在我的测试方法中不起作用?有什么想法可以调试吗?

编辑:这是来自 TaskCompletionSource 方法的代码:

TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();

        myObject.RefreshReady += (_, s) =>
        {
            //never hit
            tcs.TrySetResult(null);
        };

        myObject.Refresh();

        await tcs.Task;

        Assert.Fail(); //never hit

EDIT2:即使在测试了建议使用单独线程的方法之后,这仍然不起作用。

我尝试在 WindowsForms 项目(而不是在单元测试项目中)中使用这些方法(即使不是必需的),以确保没有缺少程序集或测试的执行方式。

所以我得到了同样的行为。我怀疑主线程中的某些东西阻止了 autoresetevent 正确设置。

——伊戈尔

标签: c#multithreadingvisual-studiounit-testing

解决方案


我个人建议在操作某些对象事件时不要使用 AWAIT 表达式,事件总是从 main_thread 触发,因此如果您处于等待链进程中,该事件将永远无法通知主线程。

您可以做的一种方法是为预期的操作创建一个新线程,它不会锁定主线程。


推荐阅读