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

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

问题描述

我想测试该设置一个特定的属性(或更一般来说,执行一些代码)会在我的对象上引发一个特定的事件。在这方面,我的问题类似于事件是单元测试在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 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 ,我来到这里:

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);
}

如您所见,我的问题在于创建一个为此事件指定适当类型的。代理人除了调用 incrementer 之外,不应该做任何事情。

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);

对于原始问题的情况:

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天全站免登陆