如何在测试方法上触发AutoResetEvent等待句柄?

时间:2019-07-03 13:01:40

标签: c# multithreading visual-studio unit-testing

在C#中进行自动测试(MSTest)的过程中,该测试方法从外部库调用方法,然后必须等待事件被触发,表明操作已完成。

我正在尝试使用this article中描述的方法:

[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 Forms应用程序而不是测试方法调用此方法,则我验证了事件是否正确触发。

内部的“ DoSomethingThatFiresAnEventEventually”方法还会调用某些方法,稍后将触发某些事件,最终将触发SomethingHappened事件。

我还尝试使用this thread中的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的正确设置。

- 伊戈尔(Igor)

1 个答案:

答案 0 :(得分:0)

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

您可以执行的一种方法是为预期的操作创建一个新线程,并且该线程不会锁定主线程。