Comparing Moq to Rhino Mocks

code, tdd 0 comments suggest edit

UPDATE: I should have entitled this “Comparing Rhino Mocks and MoQ for State Based Testing”. I tend to prefer state-based testing over interaction based testing except in the few cases where it is absolutely necessary or makes the test much cleaner. When it is necessary, it is nice to have interaction based testing available. So my comparison is incomplete as I didn’t compare interaction based testing between the two frameworks.

For the longest time I’ve been a big fan of Rhino Mocks and have often written about it glowingly. When Moq came on the scene, I remained blissfully ignorant of it because I thought the lambda syntax to be a bit gimmicky. I figured if using lambdas was all it had to offer, I wasn’t interested.

Fortunately for me, several people in my twitter-circle recently heaped praise on Moq. Always willing to be proven wrong, I decided to check out what all the fuss was about. It turns out, the use of lambdas is not the best part of Moq. No, it’s the clean discoverable API design and lack of the record/playback model that really sets it apart.

To show you what I mean, here are two unit tests for a really simple example, one using Rhino Mocks and one using Moq. The tests use the mock frameworks to fake out an interface with a single method.

[Test]
public void RhinoMocksDemoTest()
{
  MockRepository mocks = new MockRepository();
  var mock = mocks.DynamicMock<ISomethingUseful>();
  SetupResult.For(mock.CalculateSomething(0)).IgnoreArguments().Return(1);
  mocks.ReplayAll();

  var myClass = new MyClass(mock);
  Assert.AreEqual(2, myClass.MethodUnderTest(123));
}

[Test]
public void MoqDemoTest()
{
  var mock = new Mock<ISomethingUseful>();
  mock.Expect(u => u.CalculateSomething(123)).Returns(1);

  var myClass = new MyClass(mock.Object);
  Assert.AreEqual(2, myClass.MethodUnderTest(123));
}

Notice that the test using Moq only requires four lines of code whereas the test using Rhino Mocks requires six. Lines of code is not the measure of an API of course, but it is telling in this case. The extra code in Rhino Mocks is due to creating a MockRepository class and for calling ReplayAll.

The other aspect of Moq I like is that the expectations are set on the mock itself. Even after all this time, I still get confused when setting up results/expecations using Rhino Mocks. First of all, you have to remember to use the correct static method, either SetupResult or Expect. Secondly, I always get confused between SetupResult.On and SetupResult.For. I feel like the MoQ approach is a bit more intuitive and discoverable.

The one minor thing I needed to get used to with Moq is that I kept trying to pass the mock itself rather than mock.Object to the method/ctor that needed it. With Rhino Mocks, when you create the mock, you get a class of the actual type back, not a wrapper. However, I see the benefits with having the wrapper in Moq’s approach and now like it very much.

My only other complaint with Moq is the name. It’s hard to talk about Moq without always saying, “Moq with a Q”. I’d prefer MonQ to MoQ. Anyways, if that’s my only complaint, then I’m a happy camper! You can learn more about MoQ and download it from its Google Code Page.

Nice work Kzu!

Addendum

The source code for MyClass and the interface for ISomethingUseful are below in case you want to recreate my tests.

public interface ISomethingUseful 
{
  int CalculateSomething(int x);
}

public class MyClass
{
  public MyClass(ISomethingUseful useful)
  {
    this.useful = useful;
  }

  ISomethingUseful useful;
    
  public int MethodUnderTest(int x)
  {
    //Yah, it's dumb.
    return 1 + useful.CalculateSomething(x);
  }
}

Give it a whirl.

Tags: TDD , MoQ , Rhino Mocks

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

21 responses

  1. Avatar for tgmdbm
    tgmdbm March 23rd, 2008

    I'm a true convert to Moq. I love it. I agree the lambdas aren't the most natural syntax to work with. It's just the simplicity of it.
    To highlight another difference, you might want to use It.IsAny<int>() in place of IgnoreArguments().

  2. Avatar for Oran
    Oran March 23rd, 2008

    MoQ lumps its "repository" and the mock together into a single unit, which is partly why the mock.Object drill-down is necessary. You essentially get one repository per mock instead of a shared repository.
    The lack of a record/playback model is philosophical sleight-of-hand by Daniel. It's still there, it's just implicit not explicit. mock.Expect() is record, using mock.Object is playback.
    Setting expectations on the mock itself is quite doable with an extension method. Anyone can graft this on to Rhino Mocks with just a few lines of code, and I expect to see it soon in the Rhino Mocks library itself.
    MoQ is a rather unique mocking tool, both technologically and especially philosophically. I expect to see the use of lambdas catching on in all of the .NET mocking libraries. But I don't believe there is another mocking tool with the same philosophy in .NET nor in any other programming language. Maybe it's a true philosophical breakthrough, but since Daniel's arguments seem to have come from a NIH perspective rather than reflecting an understanding of the existing body of knowledge, I doubt it.

  3. Avatar for Krzysztof Koźmic
    Krzysztof Koźmic March 23rd, 2008

    To keep things straight:
    1. With Rhino.Mocks You create MockRepository once per fixture, so it's not much overhead.
    2. For this simple scenario you could use
    var mock = mocks.CreateMock<ISomethingUseful>();
    Expect.Call(mock.CalculateSomething(123))Return(1);
    So actually you get only one additional line (mocks.ReplayAll();) and IMHO nicer syntax, that reads more like english, than lambdas. And ReplayAll/VrifyAll has its advantages too. Can MoQ verify that in call to useful.CalculateSomething(x) x was actually equal 123?
    That said, I'm still resisting to convert ;)
    And on the side-note: You can read MoQ as 'mock-You', which sounds kind of funny to me.

  4. Avatar for tgmdbm
    tgmdbm March 23rd, 2008

    @Oran, In Rhino Mocks, if you ReplayAll() you can't set up any more expectations. In Moq, there really is no record/replay, you can setup some expectations, use mock.Object, setup more expectations, and use mock.Object again. All the original expectations still exist. RM has BackToRecord, but doing so removes all expectations.
    @Krzysztof, As it stands the two tests are not equivalent. The RM test ignores arguments, but the Moq test *will* assert that the argument is 123. To ignore the argument the call would be
    mock.Expect(u => u.CalculateSomething(It.IsAny<int>())).Returns(1);

  5. Avatar for Krzysztof Kożmic
    Krzysztof Kożmic March 23rd, 2008

    @tgmdbm
    Yes, I know, that's why I suggested using Expect.Call, without IgnoreArguments.
    That way it will be evrified if argument was indeed 123 when you call VerifyAll.
    And in Rhino.Mocks When you call ReplayAll() you DO can return to recording. You have to call repo.BackToRecordAll(BackToRecordOptions.None);
    or one of it's siter methods. This does NOT remove any recorded expectations.

  6. Avatar for Steven Harman
    Steven Harman March 23rd, 2008

    As Phil pointed out... counting the number of LOC does not an API make, but if you are interested in reducing the numbers for your Rhino.Mocks tests, then I'd recommend using something like the Specification base class (for Rhino.Mocks + MbUnit) or something similar depending on your testing and mocking toolsets.

  7. Avatar for tgmdbm
    tgmdbm March 23rd, 2008

    @Krzysztof, BackToRecord DOES remove expectations. Even with BackToRecordOptions.None.
    Here's an exerpt from MockRepository.cs:

    524:public void BackToRecord(object obj, BackToRecordOptions options)
    525:{
    526: IsMockObjectFromThisRepository(obj);
    527: foreach (IExpectation expectation in rootRecorder.GetAllExpectationsForProxy(obj))
    528: {
    529: rootRecorder.RemoveExpectation(expectation);
    530: }
    ...

    I've suggested to Ayende to include a bool keepExpectations parameter to the BackToRecord methods but this hasn't been implemented yet.
    With Moq tho, there is no need to know if the mock is in record or replay mode, or move the mock back to a record. It Just Works(tm).

  8. Avatar for Oran
    Oran March 23rd, 2008

    Switching back and forth between record and replay makes tests harder to read, even more so with an implicit record/replay style like MoQ's. Expectations are the mocking equivalent of Asserts, and I prefer to keep these all together for readability. Put the Expects up front, the Asserts at the end, or both. If there is the need to intersperse Expects or Asserts with the "middle" of the test, you're probably trying to cram two tests into one. Remember, you should strive to have only one (logical) assert per test.
    If the given example had used a property on the mock instead of setting a return value for a method, then the Rhino Mocks version could have been written in a similar style with the same number of lines of code as the MoQ version.
    var mock = MockRepository.GenerateStub<ISomethingUseful>();
    mock.Something = 123;
    var myClass = new MyClass(mock);
    Assert.AreEqual(...);
    One of the reasons MoQ has fewer lines of code in the given example is because the MoQ mock isn't really a mock. It's more of a stub. This is a result of Daniel's fairly extreme position of only doing state verification, not behavior verification. Even though Daniel has read Martin Fowler's essay "Mocks Aren't Stubs" [1] and uses it in his arguments for MoQ's unique philosophy, he hasn't demonstrated a clear understanding of the fact that, well, mocks aren't stubs. The intro to Martin's essay talks about how he used to confuse mocks with stubs but later realized the differences, hence the essay. Daniel has read this but comes away with Martin's pre-enlightenment perspective, not the perspective that Martin argues for in the essay. That would be fine if he thought he understood Martin's arguments and consciously chose to disagree with them, but instead he believes he's saying the same thing that Martin is. You can see some of his misunderstanding in the comments on Ayende's blog. [2]
    [1] http://martinfowler.com/art...
    [2] http://www.ayende.com/Blog/...

  9. Avatar for Haacked
    Haacked March 23rd, 2008

    @Oran Ah! I see. I've written before that I generally prefer state-based testing over interaction testing. Not that I don't use or like interaction based testing, just that I tend to use state-based testing more often. This might explain why I was drawn to MoQ.
    Both Rhino Mocks and MoQ support that state-based testing.
    So my comparison is incomplete. I used both frameworks to create Stubs or Fakes (using Fowler's hierarchy) but not Mocks. I should play around with doing interaction based testing with both to see what that looks like.

  10. Avatar for Jeremy Gray
    Jeremy Gray March 24th, 2008

    @tgmbdm - Just to weigh in alongside Oran so it is clear that he is not alone in his feelings, re: "In Moq, there really is no record/replay, you can setup some expectations, use mock.Object, setup more expectations, and use mock.Object again." that's not a feature, that is a code smell.
    While I'm not a hardline "one assertion per test" type of person (I tend to think that one _group_ of logically-associated assertions per test is a good aim), the only time you're going to switch back into record mode is in a test that makes multiple sets of logically-associated assertions. Mocking frameworks should, if anything, make the switch back into record mode require even more effort and result in even more visible code smells.

  11. Avatar for tgmdbm
    tgmdbm March 24th, 2008

    @Jeremy, I do agree with you.
    The only reason I return to record mode is when testing redirects in MVC. I first set up expectation on Redirect and capture the URL. after the target invocation I fake out the request url and querystring and call RouteTable.Routes.GetRouteData passing in the current mock context. I then assert against the returned routedata.
    As you suggest, I'm only making one logical assertion. but i've still had to return to record mode.
    It's been said before that testing redirects is a lot more difficult than it should be. Perhaps it might be possible to do this using a strict Expect>Invoke>Assert method in a future release of MVC. But for now this is the cleanest solution I've found.
    The problem here is, to get the route data from a url, you need to pass in a HttpContextBase.
    This ties in with this discussion, http://forums.asp.net/t/122...
    Maybe there could be an overload of GetRouteData which simply took a string url!?

  12. Avatar for Daniel Cazzulino
    Daniel Cazzulino March 24th, 2008

    For many more reasons on why we created Moq (let's pronounce it mock-you to disambiguate ;)) see http://snurl.com/moq-why
    The record/replay *implementation detail* of most other mocking frameworks is so much embedded into some people's minds that they try to see it even when it does not exist in reality. @tgmdbm really got it: there's NO record/replay phases in Moq. NONE. Arguing that using Mock.Object is playback is stretching the concept, when in reality there's no transition of state in the mock between one and another (non-existent) phases.
    @Oran, I don't expect you to have read all my blog posts on the reasoning for Moq's existence, but they do explain in quite some length why we came out with it. It's not NIH, it's the result of taking an existing problem domain and tackling it with a new perspective, purposedfuly ignoring existing preconceptions, to come up with something useful that doesn't assume prior knowledge from potential users (newcomers find it immediately familiar). And I say WE because it's not just ME that came up with it. The need was shared among two companies working on very real-world projects. It's the result and the evolution of what we use every day.
    @Krzysztof Kozmic: you can always call mock.VerifyAll() in Moq.
    @Oran note how your added example is now using MockRepository.GenerateStub<ISomethingUseful>(), which means now someone using the framework has to know the difference between that and a "true mock". I've argued in the past that the distinction is irrelevant in practice.
    Through our discussion on Ayende's blog, I finally clarified my own ideas around the topic: I agree with Fowler (and THAT was the context of my reference to his work) with the two styles of testing (and @Oren you also said you didn't agree with him), but I believe most developers don't/shouldn't care about the differences between mocks, stubs and fakes. They should use whatever they need, whichever the name. Hence, in Moq, you have a single concept, which can move on that continuum between those.
    @Haacked Moq is equally effective for interaction based testing, though I also like state based better :)
    @Jeremy @Oran - The point of being able to add expectations to a mock is so that you can reuse default expectations that are set through a test fixture setup. That's very useful when you have quite some wiring to do between related mocks (something like MVC hook-up) and you want to put all that in a single place. You never need to worry about the "state" (record/replay) of the mock as there's no such state in Moq.

  13. Avatar for Oran
    Oran March 24th, 2008

    Daniel, several months ago I carefully read all of your blog posts and comments regarding Moq (including the very cool strongly-typed reflection stuff), so I do understand what motivated you to write your own. I'm sure it meets your needs and fits your style. It is also rather opinionated software (along the lines of DHH and Ruby on Rails) which is both a good thing and a bad thing. Rhino Mocks and TypeMock are also rather opinionated pieces of software, so there is going to be a fair bit of passion for and against each of these tools. It will be interesting to see how things shake out.
    I understand that Moq doesn't explicitly switch between record and playback states. I'm just saying it's still implicitly there. You still set expectations and then use the mock. In Phil's Moq example, he put a blank line between the setup/record phase and the playback phase, and I expect many people will do the same to clearly distinguish which "mode" they're in. I personally like Rhino Mocks' using()-style syntax, but that's just me.
    using (mocks.Record())
    {
    Expect.Call(...);
    }
    using (mocks.Playback())
    {
    ....
    }
    I think it's interesting that MockFactory was added to Moq last month, with Verify/VerifyAll methods. This is the equivalent of Rhino Mocks' MockRepository, enabling Phil's Moq example to be rewritten in the same style as the Rhino Mocks example. I'll bet you could put a using()-friendly wrapper on it to make it even easier to work with... ;-)
    I do like the continuum idea where you start loose and opt into just the strictness you need, but that's still a concept the user has to understand and care about. Moq's MockBehavior [1] enum (Strict, Normal, Relaxed, Loose, Default) is just a different way of accomplishing this, and I would argue it's just as confusing as Rhino's 4 different types of mocks that you were poking fun at a week ago. Rhino's mocks.CreateMock<T>() is equivalent to Moq's new Mock<T>(MockBehavior.Strict). I do like the discoverability and consistency that MockBehavior adds, but it implements the exact mock continuum concepts that you say developers shouldn't care about or understand. It just bugs me that you take the rich feature set of other mock frameworks and spin them as unnecessary complexity, and then you go and implement the exact same features in Moq after the fact.
    [1] http://www.clariusconsultin...

  14. Avatar for Daniel Cazzulino
    Daniel Cazzulino March 24th, 2008

    Indeed Oran, we're all passionate about the stuff we're proud of :)
    MockFactory was added because people wanted to do a single Verify/VerifyAll call and have all used mocks verified. But still, note the Verify version is there, to allow you to verify only stuff you mark as Verifiable(). I think this is quite unique. We even have a proposal to add an overload receiving a "verification group" to it, like Verifiable("MultiUser"), so people is finding it quite useful to have more granular control about which expectations they want to verify or not.
    To me, that's a case where they don't care/even know that they are going from a Stub to a Mock when they do that. Yes, the API implements those ideas, but in a way which is completely hidden to the user, who just sees a simpler concept (do you want to verify this or not?) and an API that guides them easily.
    MockBehavior enum explicitly doesn't use Stub|Fake|TrueMock for the very same reason I still hold: users don't care what it's theoretically called by pundits/experts/academia/etc.. The resulting behavior is more or less strictness on the mock. That's what users care about. That's the ultimate meaning of what I say WRT to Stub/Fake/Mock naming and concepts.
    I'd even go as far as renaming Loose to NeverThrow, and Relaxed as ThrowIfNoReturnValue, which are easier to understand. It would never occur to me to rename those to "Stub" or the like. That's Moq spirit. And I don't think there's a classification for our Relaxed bahavior, btw...
    We did have a proposal to add using(), but we're evaluating the best syntax, as we have different kinds of verification. Also, the using() syntax is less explicit and precludes reuse of the factory through test fixture setup/test/teardown, which is an important drawback IMO. But we might just give users more choice if they so wish to.
    But not that our factory is NOT a repository: it's just a list of mocks where we call Verify/VerifyAll. Expectations are still owned by each mock. So conceptually they are still quite different.

  15. Avatar for Colin Jack
    Colin Jack March 26th, 2008

    From the look of this discussion and the blog entries it looks like Moq is moving towards being another mocking framework in the same vein as Rhino.
    I must also admit, and maybe I need to play with Moq to get it, I'm not seeing the big difference in approaches. As Oran said you still have record/playback its just a little less explicit. If you actually want mocking then at the minute there is no other choice than record/playback (from what I've seen).
    I personally find the more interesting distinction to be between TypeMock and other frameworks, and between real mockist (outside-in and role based) development and classicist development. Those choices have a real effect not just on how you test but potentially upon the resulting designs.

  16. Avatar for Daniel Cazzulino
    Daniel Cazzulino April 2nd, 2008

    Just wanted to give you a heads-up that thanks to user feedback (Oren's point taken too) feedback, we'll be simplifying the MockBehavior API to just Strict and Loose (http://code.google.com/p/mo.... This hopefully acknowledges that we indeed don't need the added complexity, and just those two settings suffice. We've found they do in our own projects.
    Next version will no longer contain the documentation or intellisense for the additional (seldom used, we learned) members (they will be there just to redirect people via [Obsolete] to the appropriate replacement), and will be gone in the following version.
    A difference I think is important is that in Moq, expectations are a different thing to verification. So you can use expectations to set return values you never verify (stub?). We have proposals to make verification even more flexible, so this seems to have been a good design decision so far...

  17. Avatar for Martin Platt
    Martin Platt May 10th, 2008

    Okay, one thing that I haven't been able to do, and wondered if it is supported, or if it's just something that you guys might be able to help with:
    If in my code, I have a foreach loop, previously I've used something to expect that GetEnumerator() would be called, followed by Expectations on the enumerator to get the Current property of the enumerator to return data to the code.
    When I tried this with Moq, it didn't work, it didn't seem to ever get called. The external property is Current (using NMock2 for example) but if I miss the expectation, Moq tells me that it is get_Current that should be expected, which tells me that it is indeed the get for the current property. However, all I have avilable to me is currrent. Am I mising something?
    So if I wanted to mock the return of data I might want the foreach loop to return 1, 2, 3 for example:
    mockedForEachList.Expect(x => x.GetEnumerator()).Returns(mockedEnumerator);
    mockedEnumerator.Expect(x => x.MoveNext()).Returns(true);
    mockedEnumerator.Expect(x => x.Current).Returns(1);
    mockedEnumerator.Expect(x => x.MoveNext()).Returns(true);
    mockedEnumerator.Expect(x => x.Current).Returns(2);
    mockedEnumerator.Expect(x => x.MoveNext()).Returns(true);
    mockedEnumerator.Expect(x => x.Current).Returns(3);
    mockedEnumerator.Expect(x => x.MoveNext()).Returns(false);
    mockedEnumerator.Expect(x => x.Dispose());
    In this circumstance is seems that my Expects make the moq'ed object to return like a stub, and I get an endless loop - how do I do this, please?
    Cheers,
    Martin Platt.

  18. Avatar for Urs Enzler
    Urs Enzler May 30th, 2008

    Very interesting discussion here.
    But I'll stick with NMock2 (http://sourceforge.net/proj... because:
    - it provides easier syntax than both MoQ and Rhino Mocks
    - the hybrid style of Rhino Mocks with mixed expectations and record operations is unnecessary complex in my opinion
    - use of lamba expressions in MoQ is not very readable either
    - tests are read much more than written -> optimize readability
    - it has no limitations that come into the way of my daily work
    - no support for out/ref parameters in MoQ (as said in docu)
    We tried to integrate lambda expressions into NMock2 but currently we think that the "magic string" approach is the only one that brings no CLR based limitations to the expectation DSL.
    Therefore, I'll stick with NMock2 and a good refactoring tool that makes refactoring of "magic strings" as simple as refactoring of compiler checked code.
    Just my thoughts, though.
    Happy mocking, Urs

  19. Avatar for Andrew
    Andrew December 13th, 2008

    Just a short note for someone who may have googled this page.
    Yeah NMock2 uses strings but you can write an extension for it:

    internal static IMatchSyntax On<T>(this IReceiverSyntax syntax, object x, Expression<Action<T>> func, params object[] args)
    {
    string name = ((MethodCallExpression)func.Body).Method.Name;
    return syntax.On(x).Method(name).With(args);
    }

    And the expectations would be typesafe and refactoring friendly:

    Expect.Once.
    On<IHand>(hand, h => h.TouchIron(null), Is.Anything).
    Will(Throw.Exception(new BurnException()));

    (However, I'm not sure yet how to make it more readable by passing parameters into the actual methods instead of having that "params object[] args" in the extension.)

    Happy mocking,
    Andrew

  20. Avatar for A
    A January 18th, 2010

    hi I am new to MOQ. Can you please tell me why we use it. I need to incorporate the MOQ in my applications.

  21. Avatar for James Radford, Web Developer
    James Radford, Web Developer June 3rd, 2010

    Hi, thanks for the post, didn't know the difference until now.. The solution I'm currently working on is fairly tied down with the Rhino Framework but at least I have some sort of clue what's the difference between them now..
    Cheers,