Mocking Events [With RhinoMocks]

3 04 2008

Suppose we have an Inerface called IFooDatabase . Think this Interface as our gateway which will provide us with basic database operations.

Now, how does Mocking come here? – My friend is still working on this database layer but he has given me already the Interface with which he is implementing the Database Class, so that I can make use of that and mock, as if that database layer exists and test my program against it.

What mocking framework I am using? – RhinoMocks

My friend told me that he is going to add events for each database operation, like InsertEvent, UpdateEvent, DeleteEvent so that they may be raised for each insertion, updation and deletion operations respectively.

For this post, to make it simple, let me take just the InsertEvent. Here is the class diagram,

And here is my Class which is going to make use of this Interface

I was pretty happy that my friend provided me an Interface to mock all the database activities, but I was really stuck on how do I test all those Events are raised!

Well, been using one of the best Mocking Frameworks around, RhinoMocks did provided a way to mock Events πŸ˜‰

So, here is my test case,

[Test]

public void TestInsertEventRaised()

{

MockRepository fooDatabaseMock = new
MockRepository();

IFooDatabase

Β Β  fooDatabase = fooDatabaseMock.DynamicMock<IFooDatabase>();

fooDatabase.FooDatabaseInsertEvent += null;

LastCall.IgnoreArguments();

IEventRaiser
fooEventRaiser = LastCall.GetEventRaiser();

fooDatabaseMock.ReplayAll();

Foo myFoo = new
Foo(fooDatabase);

fooEventRaiser.Raise(this, EventArgs.Empty);

Assert.IsTrue(myFoo.InsertEventRaised);

}

RhinoMocks provides an interface called IEventRaiser which you can use to raise events!

Here is what we are doing,

  • I am assigning null to the EventHandler and telling RhinoMocks that please do ignore the arguments in my last call. This helps us because we may associate our event to any Event Handler with different event arguments
  • We initialize IEventRaiser by getting the last event, which in our case is FooDatabaseInsertEvent
  • We pass on the Database object which is mocked to my Foo class to use
  • And finally we raise that last event
  • And do a simple Boolean check to see actually we did raise the event

Wasn’t that easy πŸ˜‰

You may complain that I have used the generalized EventArgs and completed this post. What about custom EventArgs?

No worries, that also takes the same route πŸ˜‰

[Test]

public void TestUpdateEventRaised()

{

MockRepository fooDatabaseMock = new
MockRepository();

IFooDatabase

Β  fooDatabase = fooDatabaseMock.DynamicMock<IFooDatabase>();

fooDatabase.FooDatabaseUpdateEvent += null;

LastCall.IgnoreArguments();

IEventRaiser fooEventRaiser = LastCall.GetEventRaiser();

fooDatabaseMock.ReplayAll();

Foo myFoo = new
Foo(fooDatabase);

fooEventRaiser.Raise(this, new
FooDatabaseEventArgs(“datbase”,true));

Assert.IsTrue(myFoo.UpdateEventRaised);

}

The FooDatabaseEventArgs is our custom EventArgs.

I would recommend anyone reading this post to try out the sample posted below if you really want to understand what is happening πŸ˜‰

You can download the sample here

Advertisements

Actions

Information

3 responses

3 04 2008
Owen Evans

Mocking events in one thing that needs to be added to Moq to make it as useful as Rhino Mocks.

just one thing and i’ll keep repeating myself here, be really careful what you expect, just decide if you’re a mockist or classisist and realise that the mockist way can cause more work http://martinfowler.com/articles/mocksArentStubs.html#SoShouldIBeAClassicistOrAMockist (essentially your coupling your tests with your implementation a bit more than usual)

Event raising with mocks is a really powerful tool and should be understood, especially if you ever intend to go down the Model-View-Presenter pattern as you’ll be firing a lot of events back to the presenter from the view. Then again i guess we’re all going to be using MVP now πŸ™‚

4 04 2008
Chaks

Hi Owen, yes, I did ask about this testing events using Moq and they told me that it will be added in future, but I agree Moq is really a good tool πŸ™‚

8 05 2008
deepika

i have tried it this way : fooEventRaiser.Raise(this, new
FooDatabaseEventArgs(β€œdatbase”,true));
for my custom event args but it really doesn’t work!!!! any idea why?

i get error : IAPICustomerSettingsView.add_CategoryChanged(any); Expected #1, Actual #0.

i am doing following in record() section

viewMock.CategoryChanged += null;
ChangeCategoryEventRaiser = LastCall.IgnoreArguments().GetEventRaiser();

and following in playback() section:

ChangeCategoryEventRaiser.Raise(null, new ChangeCategoryEventArgs(3));

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: