Today I was writing a unit test for a winforms application (or rather a small Mvc framework for winforms) and I would like to simulate a button click on the form to se that all events had been wired correctly.
Since the event is a delegate, I thought it would be easy to just call the Invoke/DynamicInvoke methods of the Click delegate instance to get the events fiering...
It wasn't quite that easy though. When I tried to use the code
button.Click.Invoke(this,EventArgs.Empty);I got a compiler error
The event 'System.Windows.Forms.Control.Click' can only appear on the left hand side of += or -=
After a search I found an article by Partha S that summarized the issue quite well, namely the difference between an event and a delegate is that the event can control the chaining and the event can only be invoked from within the declaring class. Partha also provided a solution for declaring an event that can be called from external code but that don't help me since I cannot modify the Button class.
A workaround is then to use reflection for retrieving the delegate field from the button class and when we have direct access to the delegate (not through the event wrapper construct) we will be able to Invoke the event.
The code below contains a method "GetField" that is included in our base library that I can post if anyone is interested, but for now it returns the value of a field.
//All events in a Component is listed in an EventHandlerListSo now I can click da button in my unittest :)
//called events in the Component class.
//b is the button instance.
EventHandlerList list = ReflectionUtil.GetField(
typeof(Component), "events", b) as EventHandlerList;
Assert.IsNotNull(list,"Cannot get eventlist from component");
//in the EventHandlerList, each delegate is identified by a
//static object instance in the control class
object eventClick = ReflectionUtil.GetField(typeof(Control),
//now we get the click event delegate
Delegate click = list[eventClick];
//finally we can invoke the listeners of the click event.