使用Moq实例</teventargs>引发EventHandler <teventargs>事件

时间:2015-03-19 14:26:22

标签: c# unit-testing moq

我有接口

public interface IBar
{

}

public interface IFoo
{
    event EventHandler<IBar> MyEvent;
}

和一个班级

public class Foobar
{
    public Foobar(IFoo foo)
    {
        foo.MyEvent += MyEventMethod;
    }

    private void MyEventMethod(object sender, IBar bar)
    {
        // do nothing
    }
}

现在我想使用Moq 4对这段精彩的代码进行单元测试:

[Test]
public void MyTest()
{
    Mock<IFoo> foo = new Mock<IFoo>();
    Mock<IBar> bar = new Mock<IBar>();

    Foobar foobar = new Foobar(foo.Object);

    foo.Raise(e => e.MyEvent += null, bar.Object);
}

根据我的理解,应该通过加注来调用Foobar.MyEventMethod。会发生什么事情,我得到一个运行时异常,说明System.Reflection.TargetParameterCountEception {&#34;参数计数不匹配。&#34;}。

有趣的是:当我在单元测试中提出以下内容时:

foo.Raise(e => e.MyEvent += null, EventArgs.Empty, bar.Object);

一切都按我的意愿运作。任何人都可以解释为什么呼叫需要三个参数?

谢谢

2 个答案:

答案 0 :(得分:6)

我假设您使用的是.NET 4.5。 Type constraint was removed from EventHandler<TEventArgs>允许你做这样的事情:

event EventHandler<IBar> MyEvent;

IBar只是某个界面

IN 4.0,约束限制TEventArgs可分配给EventArgs类型,您的代码无法编译。

由于这一点(IBar不是来自EventArgs),Moq并不认为您的活动为"corresponding to Event Handler pattern",并将其视为任何其他代表:

// Raising a custom event which does not adhere to the EventHandler pattern
...
// Raise passing the custom arguments expected by the event delegate
mock.Raise(foo => foo.MyEvent += null, 25, true);

这意味着您必须提供所有参数,包括发件人

答案 1 :(得分:5)

第一个不工作的原因,因为EventHandlers有2个参数(对象发送者,EventArgs args)。

当您设置模拟

foo.Raise(e => e.MyEvent += null, EventArgs.Empty, bar.Object);

e => e.MyEvent += null是告诉Moq要提升哪个事件的表达式,

以下2个参数是您要用它引出的2个参数。

EventArgs.Empty, bar.Object

注意:如果内存对我有用,那应该是相反的。

当您尝试使用1个参数(bar.ObjectMoq引发事件时,会抛出异常,说事件处理程序需要2,因为它使用反射来调用它。

你的第一个案子可以这样写:

public class Foo : IFoo
{
    public event EventHandler<IBar> MyEvent;

    public void OnMyEvent(IBar bar)
    {
        MyEvent(EventArgs.Empty)
    }
}

这给你一个编译错误:委托'EventHandler'不带1个参数

这就是为什么你需要2个参数,就像你用以下方法调用它一样:

public class Foo : IFoo
{
    public event EventHandler<IBar> MyEvent;

    public void OnMyEvent(IBar bar)
    {
        MyEvent(this, bar);
    }
}