Mock Objects… Firing Events
UPDATE: I finally am posting the source here!
It has been long enough since I've made my last post, but with the recent posting from Eli's blog about TypeMock on Firing Events when mocking/testing, I thought I would throw out my solution to this problem for those of us using NMock2.
If you're not familiar with mock objects, there is some great content out there, just google it (you didn't think I was actually going to explain them here did you?!)
First off, I love NMock2. It does what I need and stays out of my way. The syntax is terse and flows like prose.
On with the content!
Part 1: Ready
It seems obvious to me, that if you're using mock objects, you're most likely going to run across a mock that needs to fire an event. It's almost like the NMock2 guys completely skipped over this use case (but I'm not knocking them, this is a great product). After digging around in reflection trying to figure how to do what I wanted and discussing it with a colleague of mine, I was turned on to the idea of using Custom Actions to catch the event add's and remove's [part 1] and store them off for invocation later (when the event is actually fired) [part 2].
Part 2: Aim - Catching the Event Add's and Remove's
The great thing about a custom action (type IAction), is that you get all sorts of information about the thing that actually got invoked. In our case, the adder or remover of an event. Similar to properties, the add/remove 'accessors' are compiled into methods just like the get/set accessors. The naming of these generated methods is also similar. For a property's get/set, the names look like:
get_<PropertyNameHere>
set_<PropertyNameHere>
Likewise, for the add/remove 'accessors' for an event get names:
add_<EventNameHere>
remove_<EventNameHere>
Armed with this information, we can tell if the method being called is an event adder/remover. The syntax for catching an event add is as such:
Expect.Once.On(mockButton).EventAdd("Click",
Is.Anything).Will(Catch.EventAdd);
Similarly, event removal looks like:
Expect.Once.On(mockButton).EventRemove("Click",
Is.Anything).Will(Catch.EventRemove);
Part 3: Fire!
Great! We know when events are added! But wait, it still seems like we haven't gotten anywhere (but really we have). The Catch.EventAdd takes the method that got called (add_Click), and grabs the single argument from the method call which happens to be an EventHandler type delegate (in this case), and stores it off to be invoked later when the event gets fired.
Event.Fire("Click").On(mockButton).With(this,
EventArgs.Empty);
This call invokes all of the methods that were caught when being added to the mockButton's Click event with the given parameter values.
Often times it is useful for an event to be fired when some other mocked method gets called. For this case, a custom action should suit just fine; simply pass it into the Will portion of your expectation/stub setup for that particular method. That means, as soon as the mocked method gets called, the event will fire just as if the above line of code was executed.
Expect.Once.On(mockButton).Method("PerformClick").
Will(Event.Fire("Click", mockButton, this,
EventArgs.Empty));
Here is a complete example that pulls it all together:
interface IButton
{
event EventHandler Click;
void PerformClick();
}
class ButtonTester
{
private bool clicked;
[SetUp]
public void Setup()
{
clicked = false;
}
[Test]
public void TestButtonFire()
{
Mockery mocker = new Mockery();
IButton mockButton = mocker.NewMock(typeof(IButton)) as IButton;
Expect.Once.On(mockButton).EventAdd("Click", Is.Anything).Will(Catch.EventAdd);
// Normally exercise domain code here,
// but we'll keep it simple and inline.
mockButton.Click += delegate(object sender, EventArgs args) { clicked = true; };
Event.Fire("Click").On(mockButton).With(this, EventArgs.Empty);
Assert.IsTrue(clicked);
mocker.VerifyAllExpectationsHaveBeenMet();
}
[Test]
public void TestPerformClick()
{
Mockery mocker = new Mockery();
IButton mockButton = mocker.NewMock(typeof(IButton)) as IButton;
Expect.Once.On(mockButton).EventAdd("Click", Is.Anything).Will(Catch.EventAdd);
Expect.Once.On(mockButton).Method("PerformClick").Will(Event.Fire("Click", mockButton, this, EventArgs.Empty));
// Normally exercise domain code here,
// but we'll keep it simple and inline.
mockButton.Click += delegate(object sender, EventArgs args) { clicked = true; };
mockButton.PerformClick();
Assert.IsTrue(clicked);
mocker.VerifyAllExpectationsHaveBeenMet();
}
}
Thats it. This stuff is currently unreleased, but feel free to send requests, I'll gladly send a copy.

January 7th, 2007 - 02:30
I’m aving a problem finding the type Catch when adding events and removing events. I have the latest download from nmock.org. Could you tell me what is missing? Assembly?
January 8th, 2007 - 03:27
Jon,
I’m lucky to have stumbled onto your blog, as this is exactly the sort of thing I was looking for. Since I’ve just recently started using NMock2, I’m a bit confused as to how you’ve implemented your custom action Catcher. Also, could you go into more specifics about Event? Even better – could you post the source code or send it to me? It would help out tons.
Thanks,
Tony
January 8th, 2007 - 09:08
Joe,
The Catch type is not in the nmock2 release, it is a custom “addon” I have created. I shall post the assembly soon so you can use it (I’ll try to get to it by the end of the day). Thanks for your interest, I’m glad someone may find it useful.
January 11th, 2007 - 11:49
Jon,
You’re going to hate me for rushing you, but is there any chance that you could email me the assembly (preferably source) before you finish the post you mentioned in your reply to Joe. I’m a bit stuck in my project, and as far as I can tell, yours is the only solution I’ve found with NMock2. Any help is much appreciated.
Thanks,
Tony
January 16th, 2007 - 07:28
Jon,
We are currently using NMock2 and have just hit the brick wall of trying to unit test an event handler – and then I came across your article.
Extremely helpful – is it available yet?
Thanks.
March 1st, 2007 - 09:54
Jon,
This is exactly what I’ve been looking for!
Written my UI using the MVP pattern, and really need to be able to fire events from mocks.
If this is available, I’d love to get a copy.
Thanks!
March 6th, 2007 - 05:38
Jon,
thats great stuff you are describing. Its exactly what I’m looking for for a long time. Is your ‘Catch’ class available for download somewhere?
Thanks!
April 17th, 2007 - 00:55
neat but where is the code?
April 17th, 2007 - 07:44
Jon,
Have you released your code yet? This solves a very glaring omission in an otherwise useful tool.
Thanks for taking this on!
May 29th, 2007 - 02:20
Jon,
thanks for the article, as mentioned above this solves unit testing problem when using MVP pattern. Could you please send me the sources?
Thanks again!
September 27th, 2007 - 05:58
Hi Jon,
Your Catch and Event classes look very useful for what we are doing right now. Could I get a copy of the source? I don’t care what state it is in. Even a post on how they work would be great.
Thanks
October 6th, 2007 - 01:57
Thank you for sharing!
October 27th, 2007 - 09:58
Jon, could you post o send me the assembly (or code) of your helper class?
thanks!
November 14th, 2007 - 09:45
So did this get added into NMock2?? I know it’s there now because I just used it and wondered “Is this what Jon-Boy wrote??”. Thought I’d let you know I’m using it and I was curious as to whether I was using your code or not.
November 14th, 2007 - 09:49
I lied..it’s not there…looking at completely the wrong thing…can you send it my way??
December 25th, 2007 - 10:39
I definitely agree with the fact that this code is very useful. NMock2 team actually added code for Fire.Event… but it was not added to the compiled version. And for some reason i cant download the source code from SourceForge.
Anyway, it will be very helpful for me is you can send your code.
Thanks for this.
March 6th, 2008 - 08:45
It’s exactly what I was searching for.
Could you send me a version of this code ?
Thank you very much
Sharpmao
April 29th, 2008 - 09:20
Very usefull.. but i feel like its a honeytrap!
please can we have the code
April 29th, 2008 - 09:54
To answer everyones question, this now appears to be part of NMock2… Have fun
May 31st, 2008 - 06:50
Fire.Event and Expect.Once.On(…).EventAdd() are part of NMock2 now.
To complicate everything, there are currently two versions of NMock(2):
- nmock.org: NMock V2.0 RC 2
- http://sourceforge.net/projects/nmock2: NMock2 V1.0
I’m involved with the second one, which is in version 1.0 which is based on nmock V2.0 RC 1 and contains many improvements.
happy mocking
September 2nd, 2008 - 22:53
wow
its very reasonable article.
Good post.
realy gj
thx