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

4
我将使用Silverlight单元测试框架来测试一些视图管理器类。某些测试需要触发“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 并在等待超时时进行超时,会更好吗?

示例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();
}

现在我已经写了三个例子,它们都能工作。我的最后一个问题是:

  • 哪一个性能最佳?(即使差别微小,只是纯学术上的好奇心。)
  • 这三个例子中有没有基本缺陷?

我想要补充一点基本缺陷,那就是单元测试不应该如此复杂 :-) - Jeff Wilcox
1个回答

5
在这三个例子中,如果没有实际运行的代码,我不知道我能否给出权威的答案,但我的建议是使用#2,并且远离#1和#3。
我已经查看了Jeff Wilcox的Silverlight Unit Test Framework源代码,我记得他为EnqueueConditional使用了一个聪明但真正可怕的hack,即在定时器/后台线程上重复调用传递给EnqueueConditional()的谓词,每次检查它是否返回true。(我想这不是你想要的生产代码,但对于测试框架来说足够好了。)
因此,如果您的测试需要几秒钟才能完成,我预计waitHandler.WaitOne()要么(a)被多次调用,阻塞每个线程;要么(b)阻塞可能应该做其他事情的线程。我想(c)也是可能的,即您可能会走运,WaitOne()不会阻塞任何重要内容,并且只会被调用一次。但是,毫无疑问,#2是使用此测试框架的“标准”方式,除非您有特定原因引入WaitHandle的更复杂逻辑,否则我不会尝试将测试框架推向那个方向。
话虽如此,如果有人想探究并提供更权威的答案,我很愿意听取。

1
在推荐“b”并解释其他可能的副作用方面,+1。虽然段落可以提高可读性! - Jeff Wilcox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接