该事件是在C#中提出,使用反射单元测试 [英] Unit testing that an event is raised in C#, using reflection

查看:111
本文介绍了该事件是在C#中提出,使用反射单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要测试,设置某个属性(或者更一般地,在执行一些代码)提出了我的对象特定事件。在这方面,我的问题是类似的http://计算器。 COM /问题/ 248989 /单元测试 - 也就是说,一个事件,是公募式-C ,但我需要很多这些测试,我讨厌样板。所以我在寻找一个更通用的解决方案,使用反射

I want to test that setting a certain property (or more generally, executing some code) raises a certain event on my object. In that respect my problem is similar to http://stackoverflow.com/questions/248989/unit-testing-that-an-event-is-raised-in-c, but I need a lot of these tests and I hate boilerplate. So I'm looking for a more general solution, using reflection.

在理想情况下,我愿做这样的事情:

Ideally, I would like to do something like this:

[TestMethod]
public void TestWidth() {
    MyClass myObject = new MyClass();
    AssertRaisesEvent(() => { myObject.Width = 42; }, myObject, "WidthChanged");
}

有关的实施 AssertRaisesEvent ,我已经走到这一步:

For the implementation of the AssertRaisesEvent, I've come this far:

private void AssertRaisesEvent(Action action, object obj, string eventName)
{
    EventInfo eventInfo = obj.GetType().GetEvent(eventName);
    int raisedCount = 0;
    Action incrementer = () => { ++raisedCount; };
    Delegate handler = /* what goes here? */;

    eventInfo.AddEventHandler(obj, handler);
    action.Invoke();
    eventInfo.RemoveEventHandler(obj, handler);

    Assert.AreEqual(1, raisedCount);
}



正如你所看到的,我的问题在于创造一个代表。委托应该什么都不做,除了调用增量

As you can see, my problem lies in creating a Delegate of the appropriate type for this event. The delegate should do nothing except invoke incrementer.

由于在C#中的所有语法药水,我怎么概念委托和事件真正的工作是有点朦胧。这也是我第一次反射涉足。什么是缺少的一部分?

Because of all the syntactic syrup in C#, my notion of how delegates and events really work is a bit hazy. This is also the first time I dabble in reflection. What's the missing part?

推荐答案

我最近写单元测试事件序列的一系列博客文章为发布了同步对象和异步事件。该帖子描述了单元测试方法和框架,并提供测试完整的源代码。

I recently wrote a series of blog posts on unit testing event sequences for objects that publish both synchronous and asynchronous events. The posts describe a unit testing approach and framework, and provides the full source code with tests.

我描述了一个事件监测器,它允许编写事件排序单元实施。测试编写更干净,即摆脱所有繁琐的样板代码

I describe the implementation of an "event monitor" which allows writing event sequencing unit tests to be written more cleanly i.e. getting rid of all the messy boilerplate code.

使用我的文章中描述的事件监控器,测试可以写成像这样:

Using the event monitor described in my article, tests can be written like so:

var publisher = new AsyncEventPublisher();

Action test = () =>
{
    publisher.RaiseA();
    publisher.RaiseB();
    publisher.RaiseC();
};

var expectedSequence = new[] { "EventA", "EventB", "EventC" };

EventMonitor.Assert(publisher, test, expectedSequence);

或为实现INotifyPropertyChanged类型:

Or for a type that implements INotifyPropertyChanged:

var publisher = new PropertyChangedEventPublisher();

Action test = () =>
{
    publisher.X = 1;
    publisher.Y = 2;
};

var expectedSequence = new[] { "X", "Y" };

EventMonitor.Assert(publisher, test, expectedSequence);

和在原来的问题的情况:

And for the case in the original question:

MyClass myObject = new MyClass();
EventMonitor.Assert(myObject, () => { myObject.Width = 42; }, "Width");



EventMonitor做所有繁重的任务,并运行测试(行动),并声称事件被触发在期望的序列(expectedSequence)。它也打印出的测试失败不错的诊断消息。反思与IL是引擎盖下用来获取动态事件订阅工作,但这一切很好地封装,所以只有像上面的代码需要编写事件的测试。

The EventMonitor does all the heavy lifting and will run the test (action) and assert that events are raised in the expected sequence (expectedSequence). It also prints out nice diagnostic messages on test failure. Reflection and IL are used under the hood to get the dynamic event subscription working, but this is all nicely encapsulated, so only code like the above is required to write event tests.

有很多在描述问题和方法,以及源代码过于职位的细节:

There's a lot of detail in the posts describing the issues and approaches, and source code too:

http://gojisoft.com/blog/2010/04/22/event-sequence-unit-testing-part-1/

这篇关于该事件是在C#中提出,使用反射单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆