I have the interfaces
public interface IBar
{
}
and
public interface IFoo
{
event EventHandler<IBar> MyEvent;
}
and a class
public class Foobar
{
public Foobar(IFoo foo)
{
foo.MyEvent += MyEventMethod;
}
private void MyEventMethod(object sender, IBar bar)
{
// do nothing
}
}
Now I want to unit test this brilliant piece of code using 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);
}
From my understanding Foobar.MyEventMethod should be called through the raise. What happens is that I get a runtime exception that says System.Reflection.TargetParameterCountEception {"Parameter count mismatch."}.
Funny thing: when I Raise the following in the unit test:
foo.Raise(e => e.MyEvent += null, EventArgs.Empty, bar.Object);
Everything works as I want it. Can anybody explain why three arguments are needed for the call?
Thank you
I assume you use .NET 4.5 then. Type constraint was removed from EventHandler<TEventArgs>
which allows you to do something like this:
event EventHandler<IBar> MyEvent;
Where IBar
is just some interface .
IN 4.0, with constraint restricting TEventArgs
to be assignable to EventArgs
type, your code wouldn't compile.
As a result of this ( IBar
not deriving from EventArgs
), Moq doesn't consider your event as "corresponding to Event Handler pattern" , and treats it as any other delegate:
// 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);
Which means you have to provide all parameters, including sender .
The reason the first is not working because EventHandlers have 2 parameters (object sender, EventArgs args).
When you are setting up mocking
foo.Raise(e => e.MyEvent += null, EventArgs.Empty, bar.Object);
the e => e.MyEvent += null
is an expression to tell Moq
which event to raise,
The following 2 parameters are the 2 arguments you want to raise it with.
EventArgs.Empty, bar.Object
Note: If memory serves me right, those should be the other way around.
When you try to raise an event with 1 argument ( bar.Object
) Moq
throws an exception saying that event handler requires 2 as it uses reflection to invoke it.
Your first case could be written like this:
public class Foo : IFoo
{
public event EventHandler<IBar> MyEvent;
public void OnMyEvent(IBar bar)
{
MyEvent(EventArgs.Empty)
}
}
Which gives you a compiler error: Delegate 'EventHandler' does not take 1 arguments
So that's why you need 2 parameters, as you would invoke it with the following:
public class Foo : IFoo
{
public event EventHandler<IBar> MyEvent;
public void OnMyEvent(IBar bar)
{
MyEvent(this, bar);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.