使用 nunit 测试事件
我刚刚开始使用 TDD,并且可以自己解决我遇到的大部分问题。但现在我迷失了:如何检查事件是否被触发?我一直在寻找类似 Assert.Raise
或 Assert.Fire
的东西,但什么也没有。 Google 不是很有用,大多数点击都是诸如 foo.myEvent += new EventHandler(bar); 之类的建议。 Assert.NotNull(foo.myEvent);
但这并不能证明什么。
谢谢你!
I'm just starting with TDD and could solve most of the problems I've faced on my own. But now I'm lost: How can I check if events are fired? I was looking for something like Assert.Raise
or Assert.Fire
but there's nothing. Google was not very useful, most of the hits were suggestions like foo.myEvent += new EventHandler(bar); Assert.NotNull(foo.myEvent);
but that proves nothing.
Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
检查事件是否被触发可以通过订阅该事件并设置布尔值来完成:
由于请求 - 没有 lambda:
Checking if events were fired can be done by subscribing to that event and setting a boolean value:
Due to request - without lambdas:
我更喜欢这样做:
优点:支持多线程场景(如果在不同线程中调用处理程序)
I prefer to do as follows:
Advantages: Supports multithreading scenario (if handler is invoked in different thread)
如果您知道事件将同步触发:
如果事件可能异步触发:
但是,有人说应该避免测试异步行为。
If you know the event will be fired synchronously:
If the event may be fired asynchronously:
However, some say testing asynchronous behavior should be avoided.
我最近不得不这样做,下面是我的想法。我没有按照其他帖子所说的去做的原因是我不喜欢变量保持状态并必须在多个事件之间“手动”重置它的想法。
下面是在
MyTests
测试中测试的带有NameChanged
事件的ClassUnderTest
代码:支持的类如下。这些类可以与任何
EventHandler
一起使用或扩展到其他委托。事件测试可以嵌套。I recently had to do this, and below is what I came up with. The reason I did not do what the other posts said, is I do not like the idea of a variable keeping state and having to reset it "manually" between multiple events.
Below is the code of the
ClassUnderTest
withNameChanged
event that is tested inMyTests
tests:The supporting classes are below. The classes can be used with any
EventHandler<TEventArgs>
or expanded to other delegates. Event tests can be nested.使用 NUnit 和 Moq,您可以进行更强大的事件测试。
用于监视事件触发器的模拟类:
事件触发器的设置:
在测试中使用模拟对象:
Using NUnit and Moq you can do more robust event testing.
Mock Class used to monitor event triggers:
Setup for event Triggers:
Using Mock Objects in Tests:
我只会将 FluentAssertions 与 Nunit 一起使用: https://fluentassertions.com/eventmonitoring/ 它效果非常好。这是文档中的示例
I would just use FluentAssertions along with Nunit : https://fluentassertions.com/eventmonitoring/ it works really well. Here is an example from the docs
您可以添加自定义事件处理程序,例如,增加测试用例类中的某些整数字段。然后检查字段是否增加。
You can add your custom event handler which, for example, increments some integer field in test case class. And then check if field was incremented.
未经实战测试,可能无法在各种情况下工作(例如,委托的返回类型不是 void)。此外,它需要显式指定委托类型。最后,它不能/不测试调用事件处理程序所使用的实际参数。但我仍然想分享它,以防有人觉得它有用:
在这里,我们实际上创建了一个模拟方法,其作用类似于
THandler
类型的事件处理程序。它是通过以下步骤完成的:() => 的 lambda { Monitor.Raished() }
并且如果其返回类型为void
则符合THandler
(IMonitor monitor) = >
,用法如下:
一个 .NetFiddle 示例(不带NUnit): https://dotnetfiddle.net/RRwqAS
Not battle-tested and might not work in various scenarios (e.g. the delegate has a return type other than void). Also, it requires to explicitly specify the delegate type. Lastly, it cannot/does not test the actual arguments the event handler was called with. But still, I'd like to share it, in case someone find it useful:
Here, we actually create a mock method that acts like an event handler for type
THandler
. It is done by the following steps:(<THandler params>) => { monitor.Raised() }
and this conforms toTHandler
if its return type isvoid
(IMonitor monitor) => <previous THandler lambda>
factory
in the code) with the actual monitor instanceAnd the usage is like this:
A .NetFiddle example (without NUnit): https://dotnetfiddle.net/RRwqAS
我自己并没有真正做到这一点,但也许您可以向您想要订阅的事件添加一个虚拟事件处理程序,并让它更新本地布尔变量,以便在该方法被触发后您可以检查该布尔值的状态以查看该事件是否被解雇了?
像这样的东西:
Not really done this myself, but maybe you could add a dummy event handler to the event you wanna subscribe to and have it update a local boolean variable so that after the method is fired you can check the state of that boolean to see if the event was fired?
Something like: