Aug 27 2009

Auto-mocking hierarchies (a.k.a. recursive mocks) with Moq

Category: Uncategorizedbengtbe @ 05:35

I have just read a good post by Richard Dingwall called Law of Demeter is easy to spot when you need extra mock. He shows how you can spot violations of the Law of Demeter when you have to create extra mocks in order to stub a single method.

While I totally agree with his points about the Law of Demeter, it might not be so easy to spot violations thanks to a feature of Moq called auto-mocking hierarchies (a.k.a. recursive mocks). In this post I will show how this cool feature can simplify your tests.

System under test

Below is the code from Richard’s post that are under test:

public class ClassUnderTest

{

    public string DoSomething(IFoo foo)

    {

        return foo.Profile.GetStatus();

    }

}

public interface IFoo

{

    IProfile Profile { get; set; }

}

public interface IProfile

{

    string GetStatus();

}

The DoSomething method calls into the privates of IProfile (this is the violations of the law).

Test without recursive mocks

Below is the test without recursive mocks:

[Test]

public void Test_Without_Recursive_Mocks()

{

    const string SOME_RETURN_VALUE = “SomeReturnValue”;

    var foo = new Mock<IFoo>();

    var profile = new Mock<IProfile>();

    profile.Setup(p => p.GetStatus()).Returns(SOME_RETURN_VALUE);

    foo.SetupGet(f => f.Profile).Returns(profile.Object);

    var sut = new ClassUnderTest();

    string returnValue = sut.DoSomething(foo.Object);

    Assert.AreEqual(SOME_RETURN_VALUE, returnValue);

}

In this test we need to create an extra mock of the type IProfile to be able to mock IFoo. This makes the test much harder to read. Imagine the horror if another class was also part of the call chain.

Test with recursive mocks

Below is a simplified test that uses the recursive mocks feature of Moq:

[Test]

public void Test_With_Recursive_Mocks()

{

    const string SOME_RETURN_VALUE = “SomeReturnValue”;

    var foo = new Mock<IFoo>();

    foo.Setup(f => f.Profile.GetStatus()).Returns(SOME_RETURN_VALUE);

    var sut = new ClassUnderTest();

    string returnValue = sut.DoSomething(foo.Object);

    Assert.AreEqual(SOME_RETURN_VALUE, returnValue);

}

As you can see, we have eliminated the need for the IProfile mock. This results in a much cleaner test.

finally{}

In this post I have shown you a cool feature of Moq that can greatly simplify your mocking code. Of course you should still try to spot violations of the Law of Demeter, even though the extra mocks will no longer help you with this. Just remember that the law is really more of a guideline, but I guess Rule of thumb of Demeter doesn’t sound as catchy :)

If you want to read a great post (and discussion) about this law (eh guideline) check out The Law of Demeter Is Not A Dot Counting Exercise by Phil Haacked.

If you liked this post then please shout and kick me :)

kick it on DotNetKicks.com Shout it

Tags:

2 Responses to “Auto-mocking hierarchies (a.k.a. recursive mocks) with Moq”

  1. Andrew Kazyrevich says:

    Nice post!

    Just a small note, your "Profile.GetStatus()" example works a property accessor (althow it’s technically a method) – with it, we [i]ask[/i] for data, not [i]tell[/i] the profile to do some work.

    Accessing properties is fine – otherwise we’d have to add lots of boilerplate "delegating" getters and setters everywhere.

    What I believe LoD [b]is[/b] about, is that any method of an object should call only methods belonging to:

    1. its containing type (i.e., sibling methods/properties/fields)
    2. any parameters passed into the method
    3. any types explicitly created in the method

    I wrote a post on that recently: http://codevanced.net/post/The-Law-of-Demeter-The-crux-of.aspx so it’s still fresh in my mind :)

  2. Bengt Berge says:

    Hi Andrew!

    You raises some interesting points about the LoD, and your post about the subject was very informative. I certainly agree that the LoD is more important for methods that do work than properties. These subtleties is also why I emphasized that the LoD is a guideline and not a dot counting exercise :)

    BTW: The "Profile.GetStatus()" example was taken from Richard Dingwall’s blog.

    Bengt

Leave a Reply