如何在 UIThread 上测试 Prism 事件聚合器订阅?
我有一个类,它通过 PRISM 事件聚合器订阅事件。
由于模拟事件聚合器有点困难,如此处所述,我只是实例化一个真实的并将其传递给被测系统。
在我的测试中,我通过该聚合器发布事件,然后检查我的被测系统如何对其做出反应。由于该事件将在生产过程中由 FileSystemWatcher 引发,因此我想通过订阅 UIThread 来利用自动调度,这样我就可以在事件引发后更新我的 UI。
问题是,在测试期间,除非我不订阅 UIThread,否则该事件永远不会在被测系统中被注意到。
我使用 MSpec 进行测试,通过 TDD.Net 从 VS2008 内部运行它。 将 [RequiresSta]
添加到我的测试类没有帮助
有没有人有解决方案,可以让我在测试期间免于更改 ThreadOption(例如通过属性 - 多么丑陋的黑客)???
I have a class, that subscribes to an event via PRISMs event aggregator.
As it is somewhat hard to mock the event aggregator as noted here, I just instantiate a real one and pass it to the system under test.
In my test I then publish the event via that aggregator and then check how my system under test reacts to it. Since the event will be raised by a FileSystemWatcher during production, I want to make use of the automatic dispatch by subscribing on the UIThread, so I can update my UI once the event is raised.
The problem is, that during the test, the event never gets noticed in the system under test unless I don't subscribe on the UIThread.
I am using MSpec for my tests, which I run from inside VS2008 via TDD.Net.
Adding [RequiresSta]
to my test class didn't help
Does anyone have a solution, that saves me from changing the ThreadOption during my tests (e.g. via a property - what an ugly hack)???
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您模拟事件和事件聚合器,并使用 moq 的回调,则可以做到。
这是一个例子:
If you mock both the event and the Event Aggregator, and use moq's Callback, you can do it.
Here's an example:
我真的认为你应该对所有事情使用模拟而不是 EventAggregator。嘲笑一点也不难...我认为链接的答案并没有证明有关 EventAggregator 的可测试性的任何东西。
这是你的测试。我不使用 MSpec,但这是 Moq 中的测试。您没有提供任何代码,因此我将其基于链接到的代码。你的场景比链接的场景要难一些,因为另一个OP只是想知道如何验证订阅是否被调用,但你实际上想调用在订阅中传递的方法......更困难,但不是非常。
I really think you should use mocks for everything and not the EventAggregator. It's not hard to mock at all... I don't think the linked answer proves much of anything about the testability of the EventAggregator.
Here's your test. I don't use MSpec, but here's the test in Moq. You didn't provide any code, so I'm basing it on the linked-to code. Your scenario is a little harder than the linked scenario because the other OP just wanted to know how to verify that Subscribe was being called, but you actually want to call the method that was passed in the subscribe... something more difficult, but not very.
您可能不喜欢这个,因为它可能涉及您认为“丑陋的黑客”,但我更喜欢使用真正的 EventAggregator,而不是嘲笑一切。虽然表面上是外部资源,但 EventAggregator 在内存中运行,因此不需要太多设置和清理,并且不像其他外部资源(例如数据库、Web 服务等)那样成为瓶颈,因此我觉得它适合在单元测试中使用。在此基础上,我使用此方法克服了 NUnit 中的 UI 线程问题,并且为了测试而对生产代码进行了最小的更改或风险。
首先,我创建了一个像这样的扩展方法:
}
然后,在我的所有事件订阅中,我使用以下内容:
在生产代码中,这可以无缝工作。出于测试目的,我所要做的就是在我的设置中添加此内容,并在测试中添加一些同步代码:
为了使等待和脉冲更加简洁,我还在 ThreadingExtensions 中添加了以下扩展方法:
然后我可以做:
再说一次,如果你的敏感性意味着你想使用模拟,那就去做吧。如果您想使用真实的东西,这很有效。
You may not like this as it may involve what you feel is an "ugly hack", but my preference IS to use a real EventAggregator rather than mocking everything. While ostensibly an external resource, the EventAggregator runs in memory and so does not require much set-up, clear down, and is not a bottle neck like other external resources such as databases, web-services, etcetera would be and therefore I feel it is appropriate to use in a unit test. On that basis I have used this method to overcome the UI thread issue in NUnit with minimal change or risk to my production code for the sake of the tests.
Firstly I created an extension method like so:
}
Then, in all my event subscriptions I use the following:
In production code, this just works seamlessly. For testing purposes, all I have to do is add this in my set-up with a bit of synchronisation code in my test:
To make the waiting and pulsing more succinct I have also added the following extension methods to ThreadingExtensions:
Then I can do:
Again, if your sensibilities mean you want to use mocks, go for it. If you'd rather use the real thing, this works.