3

当我编写一个需要检查异步事件是否被引发的单元测试时,我通常会做这样的事情:

[Test]
public void test()
{
    var eventRaised = new ManualResetEvent(false);
    subject.SomeEvent += (s, e) => { eventRaised.Set(); };

    // Do something which should have triggered the event

    Assert.True(eventRaised.WaitOne(5000), "Event was not raised.");
}

但是,在我目前的情况下,事件是基于来自外部系统的不同事件引发的,我刚刚发现我实际上得到了重复的事件,这并不好。我无法更改这个其他系统,所以我需要过滤掉我班级中的重复事件。幸运的是,有一种简单的方法可以检查它是否重复,但现在我想知道我应该如何更改单元测试以确保我的过滤正常工作。

您将如何编写一个单元测试来检查在采取某个动作后,某个事件只引发一次?

4

2 回答 2

2

向单元测试添加一个计数器,并在任何时候触发事件处理程序时递增计数器。确保测试完成后,计数器值等于 1。

[Test]
public void test()
{
    int numEventsRaised = 0;
    subject.SomeEvent += (s, e) => { numEventsRaised++; };

    // Do something which should have triggered the event

    //As per the OP's example, we will wait 5 seconds to ensure
    //the async event has time to be raised.
    Thread.Sleep(5000);

    Assert.False((numEventsRaised == 0), "Event was not raised.");
    Assert.False((numEventsRaised > 1), "Event was raised more than once.");
}
于 2012-09-12T12:22:24.587 回答
1

出色地。该单元测试将需要一些时间,因为延迟必须到期(以便您确定最终的第二次发布被捕获)。

使用计数器并尝试减少超时。5 秒似乎有点长(取决于外部系统)

[Test]
public void test()
{
    var eventRaised = new ManualResetEvent(false);
    var counter = 0;
    subject.SomeEvent += (s, e) => { if (++counter) >= 2 eventRaised.Set(); };

    // Do something which should have triggered the event

    // you might want to decrease the timeout
    Assert.False(eventRaised.WaitOne(5000), "Event was not raised.");
    Assert.AreEqual(1, counter);
}
于 2012-09-12T12:30:27.637 回答