Raise an EventHandler<TEventArgs> event with a Moq instance - c#

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

Related

C# Event as method argument [duplicate]

I have the following class, which has one public event called LengthChanged:
class Dimension
{
public int Length
{
get
{
return this.length;
}
set
{
if (this.length != value)
{
this.length = value;
this.OnLengthChanged ();
}
}
protected virtual void OnLengthChanged()
{
var handler = this.LengthChanged;
if (handler != null)
{
handler (this, System.EventArgs.Empty);
}
}
public event System.EventHandler LengthChanged;
private int length;
}
I would like to be able to register/unregister handlers for this event in a method called Observer, which does not know anything about the Dimension class. I have come up with two scenarios, none of which are really satisfying:
Define an interface ILengthChanged with the LengthChanged event, then make sure Dimension implements ILengthChanged. Then I have to provide one implementation of the Observer method for every interface I define. This by no way generic enough. I'd really want to be able to simply pass in a reference to a System.EventHandler event.
Use System.Action<System.EventHandler> callbacks for registering and unregistering the event handler in the Observer method, just like that:
class Foo
{
public void Observer(System.Action<System.EventHandler> register,
System.Action<System.EventHandler> unregister)
{
register (this.MyEventHandler);
// keep track of the unregister callback, so that we can unregister
// our event handler later on, if needed...
}
private void MyEventHandler(object sender, System.EventArgs e)
{
...
}
}
which would then be invoked like this:
Foo foo = ...;
Dimension dim = ...;
foo.Observer (x => dim.LengthChanged += x, x => dim.LengthChanged -= x);
and which, when executed, will indeed end up wiring the LengthChanged event with the internal event handler MyEventHandler. But this is not very elegant. I would have loved to be able to write this instead:
Foo foo = ...;
Dimension dim = ...;
foo.Observer (dim.LengthChanged);
but I've no idea how this could be achieved. Maybe I am missing something really obvious here? I guess that some dynamic magic could do the trick, somehow, but this would not enforce compile-time type checking: I don't want the users of Observer to pass in references to events which do not satisfy the System.EventHandler event signature.
Unfortunately there isn't really a way of doing this. Events aren't first class citizens in .NET in general - although F# tries to promote them there.
Either pass in the subscribe/unsubscribe delegate or using a string indicating the name of the event. (The latter is often shorter, but obviously less safe at compile-time.)
Those are the approaches which Reactive Extensions takes - if there were a cleaner way of doing it, I'm sure they would be using that :(
You can create a custom accessor.
public event EventHandler NewEvent
{
add { Dimension.LengthChanged += value; }
remove { Dimension.LengthChanged -= value; }
}
Please see the documentation.
Event is not supposed to be passed into another method. However, you can pass delegate into another method. Perhaps, what you are looking for are just a simple public delegate instead of event.
If you change your event to this
public System.EventHandler LengthChanged;
You can simply pass the LengthChanged to Observer like this
Foo foo = ...;
Dimension dim = ...;
foo.Observer (dim.LengthChanged);

Call Delegate methods from another class

I am having trouble figuring out how to program delegate method calls across classes in C#. I am coming from the world of Objective-C, which may be confusing me. In Objective-C, I can assign a delegate object inside a child class, to be the parent class (I.e., childViewcontroller.delegate = self;). Then I can to fire a method in the delegate class by using:
if([delegate respondsToSelector:#selector(methodName:)]) {
[delegate methodName:parametersgohere];
}
However, I can't figure out how to do this in C#. I've read a bit about C# delegates in general (for example, here), but I'm still stuck.
Are there any examples that explain this?
Here is my scenario in full:
I have classA which instantiates an instance of classB. ClassB fires a method (which call a web service), and upon response, I'd like to fire a method in classA.
Any 'Hello World' types of tutorials out there that might explain the very basics of this?
A delegate is an object that points to a method, be it a static or instance method. So for your example, you would just use the event model:
class Caller {
public void Call() {
new Callee().DoSomething(this.Callback); // Pass in a delegate of this instance
}
public void Callback() {
Console.WriteLine("Callback called!");
}
}
class Callee {
public void DoSomething(Action callback) {
// Do stuff
callback(); // Call the callback
}
}
...
new Caller().Call(); // Callback called!
The Caller instance passes a delegate to the Callee instance's DoSomething method, which in turn calls the pointed-to method, which is the Callback method of the Caller instance.
In C# what I think you are looking for are called events. They are a language feature that allows a class instance to expose a public delegate in a way that other class instances can subscribe to. Only the exposing class is allowed to raise the event.
In your example:
public class ClassB {
// Note the syntax at the end here- the "(s, e) => { }"
// assigns a no-op listener so that you don't have to
// check the event for null before raising it.
public event EventHandler<MyEventArgs> MyEvent = (s, e) => { }
public void DoMyWork() {
// Do whatever
// Then notify listeners that the event was fired
MyEvent(this, new MyEventArgs(myWorkResult));
}
}
public class ClassA {
public ClassA(ClassB worker) {
// Attach to worker's event
worker.MyEvent += MyEventHandler;
// If you want to detach later, use
// worker.MyEvent -= MyEventHandler;
}
void MyEventHandler(Object sender, MyEventArgs e) {
// This will get fired when B's event is raised
}
}
public class MyEventArgs : EventArgs {
public String MyWorkResult { get; private set; }
public MyEventArgs(String myWorkResult) { MyWorkResult = myWorkResult; }
}
Note that the above will be synchronous. My understanding is that Objective-C delegates are all Actor pattern, so they are asynchronous. To make the above asynch, you'll need to delve into threading (probably want to google "C# Thread pool").

C# and Moq, raise event declared in interface from abstract class mock

I am writing the unit test and receive exception when trying to raise the event from abstract class mock. Here is the sample code:
public abstract class AbstractBase : EntityObject
{}
[TestMethod]
public void MyTest()
{
var mock = new Mock<AbstractBase>();
var notificationMock = entityMock.As<INotifyPropertyChanged>();
var propertyChangedMapper = new PropertyChangedMapper();
bool eventReceived = false;
propertyChangedMapper.MyPropertyChanged +=
(sender, eventArgs) =>
{
eventReceived = true;
};
propertyChangedMapper.Subscribe((AbstractBase)notificationMock.Object);
Assert.IsFalse(eventReceived);
notificationMock.Raise(e=>e.PropertyChanged += null,
new PropertyChangedEventArgs("Property1"));
Assert.IsTrue(eventReceived);
}
Obviously I could use mock on INotifyPropertyChanged and event is risen just fine, but inside of PropertyChangedMapper I need to cast the sender to AbstractBase which fails if using Mock<INotifyPropertyChanged>
EDIT:
As per suggestion using Mock.As<>() seems to be the right way to go, the only problem above is that the event risen from notificationMock has nothing to do with the original mock of the object. Code:
notificationMock.Object.PropertyChanged += (s, e) =>
{
var result = "this one is fired as it should";
};
mock.Object.PropertyChanged += (s, e) =>
{
var result = "this one is not called but is actually what I need";
};
notificationMock.Raise(e => e.PropertyChanged += null,
new PropertyChangedEventArgs("Property1"));
You may be able to do the desired cast if you make your mock a mult-mock. Since Moq mocks are tied to an individual type via the generic argument, you must explicitly progressively add additional interfaces or super-classes to the mock, and then use the end product in your test. A quick example of how to do this is below.
var baseMock = new Mock<AbstractBase>();
var inpcMock = baseMock.As<INotifyPropertyChanged>();
// ...setup event...
propertyChangedMapper.Subscribe(inpcMock.Object);
// ... assertions ...
Given the way you're doing this, there is no implementation of the event. The interface itself is just the contract that says "I have a PropertyChanged event." If you want to raise that event, you have to provide a handler, even if it doesn't do anything. Implement the PropertyChanged event in your mocked class to raise the event.
UPDATE:
Try this code for your AbstractBase:
public abstract class AbstractBase : INotifyPropertyChanged
{
public virtual event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
Is your PropertyChanged event declared as a virtual event?
public abstract class AbstractBase : INotifyPropertyChanged
{
public virtual event PropertyChangedEventHandler PropertyChanged;
}
(See also: Jon Skeet on virtual events.)

How can I test that an event contains an event handler?

I want to test that class A's RegisterEventHandlers() method registers one of its methods as an EventHandler for an event on class B. How can I do that? I'm using moq, if that matters.
I don't think there's a way to inspect the event handler delegate from outside the class (please correct me if I'm wrong).
It'd be nice if I could trigger the event and then assert that my callback was called, but if I mock the interface of the A class (and set up an expectation for the callback) then I lose the implementation of RegisterEventHandlers(), which is the method I'm testing in the first place.
Mocking the B class's event would be the best option, but I don't see what method I'd have to intercept to do this. Is there some way to set up a mock for an event, and intercept the += method call?
Is there a clean solution to this?
You can get the invocation list for an event outside the class declaring the event - but it involves reflection. Below is a code example showing how you can determine which methods (on target instance a) are added to the event b.TheEvent after a call to a.RegisterEventHandlers(). Paste the code below in a code file and add to a form or console project: Test test = new Test(); test.Run();
using System;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
public class A
{
B m_b = new B();
public void RegisterEventHandlers()
{
m_b.TheEvent += new EventHandler(Handler_TheEvent);
m_b.TheEvent += new EventHandler(AnotherHandler_TheEvent);
}
public A()
{
m_b.TheEvent += new EventHandler(InitialHandler_TheEvent);
}
void InitialHandler_TheEvent(object sender, EventArgs e)
{ }
void Handler_TheEvent(object sender, EventArgs e)
{ }
void AnotherHandler_TheEvent(object sender, EventArgs e)
{ }
}
public class B
{
public event EventHandler TheEvent;
//{
// //Note that if we declared TheEvent without the add/remove methods, the
// //following would still generated internally and the underlying member
// //(here m_theEvent) can be accessed via Reflection. The automatically
// //generated version has a private field with the same name as the event
// //(i.e. "TheEvent")
// add { m_theEvent += value; }
// remove { m_theEvent -= value; }
//}
//EventHandler m_theEvent; //"TheEvent" if we don't implement add/remove
//The following shows how the event can be invoked using the underlying multicast delegate.
//We use this knowledge when invoking via reflection (of course, normally we just write
//if (TheEvent != null) TheEvent(this, EventArgs.Empty)
public void ExampleInvokeTheEvent()
{
Delegate[] dels = TheEvent.GetInvocationList();
foreach (Delegate del in dels)
{
MethodInfo method = del.Method;
//This does the same as ThisEvent(this, EventArgs.Empty) for a single registered target
method.Invoke(this, new object[] { EventArgs.Empty });
}
}
}
public class Test
{
List<Delegate> FindRegisteredDelegates(A instanceRegisteringEvents, B instanceWithEventHandler, string sEventName)
{
A a = instanceRegisteringEvents;
B b = instanceWithEventHandler;
//Lets assume that we know that we are looking for a private instance field with name sEventName ("TheEvent"),
//i.e the event handler does not implement add/remove.
//(otherwise we would need more reflection to determine what we are looking for)
BindingFlags filter = BindingFlags.Instance | BindingFlags.NonPublic;
//Lets assume that TheEvent does not implement the add and remove methods, in which case
//the name of the relevant field is just the same as the event itself
string sName = sEventName; //("TheEvent")
FieldInfo fieldTheEvent = b.GetType().GetField(sName, filter);
//The field that we get has type EventHandler and can be invoked as in ExampleInvokeTheEvent
EventHandler eh = (EventHandler)fieldTheEvent.GetValue(b);
//If the event handler is null then nobody has registered with it yet (just return an empty list)
if (eh == null) return new List<Delegate>();
List<Delegate> dels = new List<Delegate>(eh.GetInvocationList());
//Only return those elements in the invokation list whose target is a.
return dels.FindAll(delegate(Delegate del) { return Object.ReferenceEquals(del.Target, a); });
}
public void Run()
{
A a = new A();
//We would need to check the set of delegates returned before we call this
//Lets assume we know how to find the all instances of B that A has registered with
//For know, lets assume there is just one in the field m_b of A.
FieldInfo fieldB = a.GetType().GetField("m_b", BindingFlags.Instance | BindingFlags.NonPublic);
B b = (B)fieldB.GetValue(a);
//Now we can find out how many times a.RegisterEventHandlers is registered with b
List<Delegate> delsBefore = FindRegisteredDelegates(a, b, "TheEvent");
a.RegisterEventHandlers();
List<Delegate> delsAfter = FindRegisteredDelegates(a, b, "TheEvent");
List<Delegate> delsAdded = new List<Delegate>();
foreach (Delegate delAfter in delsAfter)
{
bool inBefore = false;
foreach (Delegate delBefore in delsBefore)
{
if ((delBefore.Method == delAfter.Method)
&& (Object.ReferenceEquals(delBefore.Target, delAfter.Target)))
{
//NOTE: The check for Object.ReferenceEquals(delBefore.Target, delAfter.Target) above is not necessary
// here since we defined FindRegisteredDelegates to only return those for which .Taget == a)
inBefore = true;
break;
}
}
if (!inBefore) delsAdded.Add(delAfter);
}
Debug.WriteLine("Handlers added to b.TheEvent in a.RegisterEventHandlers:");
foreach (Delegate del in delsAdded)
{
Debug.WriteLine(del.Method.Name);
}
}
}
When mocking B, declare the EventHandler like this:
public class B : IB
{
public int EventsRegistered;
public event EventHandler Junk
{
add
{
this.EventsRegistered++;
}
remove
{
this.EventsRegistered--;
}
}
}
I'm not certain that moq allows this, but I'm sure you can create your own mock class.
You are correct that you cannot access the event delegates from outside the class, this is a limitation within the C# language.
The most straight-forward approach to test this, would be to mock class B and then raise it's event and then observe the side-effects of the event being raised. This is slightly different than what you're looking for but it demonstrates class's A behavior rather than its implementation (this is what your tests should strive to do).
In order for this to work, class B must be mockable and the event that it exposes must also be virtual. Moq can't intercept events if they're not declared as virtual. Alternatively, if B is an interface be sure that the event is declared there.
public interface IEventProvider
{
event EventHandler OnEvent;
}
public class Example
{
public Example(IEventProvider e)
{
e.OnEvent += PerformWork;
}
private void PerformWork(object sender, EventArgs e)
{
// perform work
// event has an impact on this class that can be observed
// from the outside. this is just an example...
VisibleSideEffect = true;
}
public bool VisibleSideEffect
{
get; set;
}
}
[TestClass]
public class ExampleFixture
{
[TestMethod]
public void DemonstrateThatTheClassRespondsToEvents()
{
var eventProvider = new Mock<IEventProvider>().Object;
var subject = new Example(eventProvider.Object);
Mock.Get(eventProvider)
.Raise( e => e.OnEvent += null, EventArgs.Empty);
Assert.IsTrue( subject.VisibleSideEffect,
"the visible side effect of the event was not raised.");
}
}
If you really need to test the implementation, there are other mechanisms available, such as a hand-rolled Test Spy / Test Double, or reflection-based strategy to get the delegate list. My hope is that you should be more concerned with class A's event handling logic than its event handler assignment. After all, if class A doesn't respond to the event and do something with it, the assignment shouldn't matter.
I don't know much about unit testing, but perhaps this link can give you some ideas. Note that the virtual keyword also works there.
I don't think moq has that capability - if you're prepared to purchase a tool I suggest you use Typemock Isolator that can verify that any method on an object was called - including event handler - have a look at link.

problem in delegate declaration and its invocation

When I try to call the event myevent in the function fire, it gives compiler error as
delegate mydelegate does not take 0 arguments.
if i try to give arguments in calling myevent as
myevent(this);
it again shows error as it does not take 1 parameters. what parameters am i supposed to give in the calling myevent? Here's the program code:
namespace useofdelegates
{
public class Class1
{ int i;
public delegate void mydelegate(object sender,EventArgs e);
public event mydelegate myevent;
public void fire()
{
myevent(this); // *** shows compiler error ***
}
}
}
The compiler error is because you are using a delegate with two parameters and calling it with one.
The simple solution is
myevent(this, EventArgs.Empty);
The more regular (and thread-safe) solution, which I think you're getting confused with is
OnMyEvent(EventArgs.Empty);
// and then later
public void OnMyEvent(EventArgs args)
{
mydelegate handler = myevent;
if(handler != null) handler(this, args);
}
The reason for doing it this way is that you should always make sure that there is at least one handler attached to the event. There is a small chance that the handler can be detached between checking for null and calling the handler, so it's good to pass it on to another variable which it cannot be detached from before checking for null.
You need to pass in 2 parameters. the first one being the source of the event. In your example "this" would work. The second one being of type EventArgs or a realted subclass. You can also pass EventArgs.Empty is you do not wish to pass any event especific information to the event handler.
So your method would look like this
fire(this, EventArgs.Empty);
or
fire(this, new MyCustomEVentArgs());
Here is an MSDN link with an example of using events http://msdn.microsoft.com/en-us/library/aa645739(VS.71).aspx
and nother one on creating custom EventArg subclasses to use in your handler. http://www.devarticles.com/c/a/C-Sharp/Creating-Custom-Delegates-and-Events-in-C-sharp/
You have declared mydelegate to require an object and an EventArgs, so you have to pass these in. Of course, you don't have declare your delegate with these arguments. You could just declare it thus:
public delegate void mydelegate();
or just pass this as the sender:
public delegate void mydelegate(object sender);
Just create an empty EventArgs I guess.
myevent(this, new EventArgs());
Note, here is the full code:
namespace useofdelegates
{
public class Class1
{
int i;
public delegate void mydelegate(object sender, EventArgs e);
public event mydelegate myevent;
public void fire()
{
myevent(this, new EventArgs()); // *** shows compiler error ***
}
}
}

Categories