等待Silverlight单元测试中的事件触发

时间:2009-12-15 05:31:17

标签: .net silverlight multithreading unit-testing

我正在使用Silverlight单元测试框架来测试一些View Manager类。某些测试需要触发 PropertyChanged 事件。

我目前正在使用 EnqueueConditional WaitHandles 的组合

示例1

[TestMethod]
[Asynchronous]
[Timeout(1000)]
public void TestNotificationExample()
{
    var manager = new UserManager();

    var waitHandle = new ManualResetEvent(false);
    manager.PropertyChanged += (sender, propChangArgs) =>
                                {
                                    waitHandler.Set();
                                };
    manager.DoTheThingThatTriggersNotification();
    // The notification event fires aynshronously to this
    EnqueueConditional (() => waitHandler.WaitOne(0));
    // Enqueue other tests here....
    EnqueueTestComplete();
}

这很有效。但我有些问题唠叨着我:

我真的需要使用WaitHandle吗?如果我只使用一个bool,它会表现得同样吗?

示例2

bool fHasFiredEvent = false;
manager.PropertyChanged += (sender, propChangeArgs) =>
                           { 
                               fHasFiredEvent = true;
                           }
manager.DoTheThingThatTriggersNotification();    
EnqueueConditional (() => fHasFiredEvent);
EnqueueTestComplete();

或者如果我保留WaitHandle会更好,但会丢失TimeoutAttribute并在Wait上超时?

示例3

[TestMethod]
[Asynchronous]
public void TestNotificationExample()
{
    var manager = new UserManager();

    var waitHandle = new ManualResetEvent(false);
    manager.PropertyChanged += (sender, propChangArgs) =>
                                {
                                    waitHandler.Set();
                                };
    manager.DoTheThingThatTriggersNotification();
    EnqueueCallback (() => Assert.IsTrue(waitHandler.WaitOne(1000));
    EnqueueTestComplete();
}

所以现在我写了三个例子,它们都有效。所以我的最后一个问题是

  • 哪个会有最好的 性能? (尽管如此 差异可以忽略不计 纯粹学术yada yada yada。它本身就很有趣。)
  • 三个例子中的任何一个都有 根本缺陷?

1 个答案:

答案 0 :(得分:5)

如果没有在三个示例中实际运行实际代码,我不知道我可以给出权威的答案,但我的建议是使用#2,并且很好地避开#1和#3。

我已经浏览了Jeff Wilcox的Silverlight单元测试框架的源代码,我记得,他对EnqueueConditional使用了一个聪明但非常可怕的黑客,即他反复调用传递给EnqueueConditional()的谓词计时器/后台线程,每次检查它是否返回true。 (这不是你想要的生产代码,但我认为它对于测试框架来说已经足够好了。)

因此,如果您的测试需要几秒钟才能完成,我希望您的waitHandler.WaitOne()要么多次调用(a),要么阻塞每个线程;或(b)阻止可能应该做其他事情的线程。我想(c)也是可能的,也就是说,你可能会很幸运,WaitOne()不会阻止任何重要的东西,并且只会被调用一次。但肯定#2是使用这个测试框架的“标准”方式,除非你有一个特定的理由来介绍WaitHandle的更复杂的逻辑,否则我不会试图将测试框架推向那个方向。

那就是说,如果有人想要四处寻找并提供更权威的答案,我全都听见了: - )。