Mocking with Moq and Rhino.Mocks

Last week I’ve read quite a few new blogposts about Moq mocking framework. I had looked at it once, when it was first released, but I didn’t find it interesting back then. Now that version 2.0 was released I decided to give it a go once again.

Here’s very simple model I created:

model

It’s a class with one method that uses helper object to obtain a value and possibly raise an event.

Here’s the whole code:

public interface IHelper
    {
        int Param { set; }
        string SomeMethod();
    }
    public class MyClass
    {
        public MyClass(IHelper helper)
        {
            Helper = helper;
        }
 
        public IHelper Helper { set; private get; }
 
        public event EventHandler MyEvent = delegate { };
 
        public void DoSomething(int parameter)
        {
            Helper.Param = parameter;
            string result = Helper.SomeMethod();
            if (result != null)
                MyEvent(null, EventArgs.Empty);
        }
    }

Now, to the fun part:

Let’s see how we can verify that when SomeMethod returns null, MyEvent is indeed not raised. First with Rhino.Mocks

   1:          [Test]
   2:          public void DoDomething_should_NOT_raise_MyEvent_when_helperSomeMethod_returns_null_Rhino()
   3:          {
   4:              var helper = _mocks.CreateMock<IHelper>();
   5:              var subscriber = _mocks.CreateMock<IEventSubscriber<EventArgs>>();
   6:              using (_mocks.Record())
   7:              {
   8:                  Expect.Call(helper.Param = 3);
   9:                  Expect.Call(helper.SomeMethod()).Return(null);
  10:                  DoNotExpect.Call(() => subscriber.Method(null, EventArgs.Empty));
  11:              }
  12:              using (_mocks.Playback())
  13:              {
  14:                  var sut = new MyClass(helper);
  15:                  sut.MyEvent += subscriber.Method;
  16:                  sut.DoSomething(3);
  17:              }
  18:          }

18 lines of code (you could cut that down to 13 simply by using ReplayAll() instead of Record() and VerifyAll in TearDown method instead of Playback, but I prefer it this way. My code is clean and quite well serves as documentation: Especially thanks to explicit usage of DoNotExpect.

The only awkward thing, is that whereas in both Expect call, I insert bare calls, in DoNotExpect.Call I had to use lambda. It’s a small inconsistency.

Now how would the same test look like with Moq?

   1:          [Test]
   2:          public void DoDomething_should_NOT_raise_MyEvent_when_helperSomeMethod_returns_null_Moq()
   3:          {
   4:              var helper = new Mock<IHelper>(MockBehavior.Strict);
   5:              var subscriber = new Mock<IEventSubscriber<EventArgs>>(MockBehavior.Strict);
   6:              helper.Expect(h => h.Param = 3);
   7:              helper.Expect(h => h.SomeMethod()).Returns((string)null);
   8:   
   9:              var sut = new MyClass(helper.Object);
  10:              sut.MyEvent += subscriber.Object.Method;
  11:              sut.DoSomething(3);
  12:          }

12 lines including one empty to visually divide setup part from testing part. Nice. There’s however one BIG problem with this code: it won’t compile. As I said earlier, You can’t have assignment in Expressions, and that’s what Moq is using, so if you want to set some properties on your mock… well – you’re out of luck. I also don’t like the fact that I have to cast null, to string. This seems redundant, but it’s only a small annoyance.

Bigger problem is that I can’t explicitly state that I expect MyEvent not to be raised.

Another thing, I couldn’t find a way to get hold of event raiser. I guess it’s just not there, so if you want to test events… you’re out of luck too.

Moq is interesting project for sure, it’s simple (simplistic) syntax made me think, about how complicated Rhino.Mocks became. Sure it’s orders of magnitude more powerful, but some unification of interfaces, even for a price of breaking some old code would be highly desired. I can imagine that for a newcomer current learning curve may seem steep. Especially the fact of using static classes makes API much less discoverable.

So I will stick to Rhino.Mocks, as it Moq is still to simple for serious use, but I’m glad it’s there. It brings some fresh ideas to the table, and there’s nothing better than a little competition.

Technorati Tags: , , ,

Comments

I think I might be missing something, but in your example, checking that MyClass didn’t raise the event is as simple as:

sut.MyEvent += delegate { Assert.Fail(“Shouldn’t be called”; };

you don’t need to go through the hassle of handling that in the mock.
I think event support in the mocks is more interesting when they are supposed to raise the events so that the object under test can react to that.

the latest preview of MoQ supports such scenario, as well as setting property values via mock.ExpectSet(…)

No, you’re not missing anything. In this example it’s really a hassle to use mock for the event, but the point of this blogpost was to compare MoQ to Rhino.Mocks, so I used mocks for that as well, but then again – maybe I’m just used to RM and wanted to do it its way.
But what if, the method looked somewhat different:
public void DoSomething(int parameter)
{
Helper.Param = parameter;
string result = Helper.SomeMethod();
if (result != null)
Helper.SomeOtherMethod();
}
And I wanted to test that SomeOtherMethod is not called. I can leave that to mock verification, that would report if it did get called, when it wasn’t expected, but I like my test to be executable documentation and be explicit about every important piece of behaviour.
I guess, (if it’s not there yet) you can treat it as request for
helper.DoNotExpect(h => h.SomeOtherMethod());

I think WRT documentation, you’ll like a lot the new Verify(…) syntax 🙂

It’s much better than DoNotExpect because it goes right where the Asserts are 🙂