The Inquisitive Coder - Davy Brion’s Blog

Thinking outside of the typical .NET box

Mocking Dilemma, Solved!

Posted by Davy Brion on July 21st, 2008

A coworker of mine, Tom Ceulemans, has provided a very nice solution to the mocking dilemma i posted earlier. I like this solution so much, i think it deserves its own post :)

The original question was basically: how do you do access a protected member in a test? I didn’t want to make it public because it is a base class, and i was hoping to avoid making it protected internal and then exposing the internals to my tests assembly.

Tom’s solution is very nice, and IMO, very clean as well. The trick is to create a derived abstract class from the class you want to test and then write the TestFixture as an inner class of the newly created class.

The test shown in the previous post would now look like this:

    public abstract class MyAbstractClassTestWrapper : MyAbstractClass

    {

        [TestFixture]

        public class MyAbstractClassTests

        {

            [Test]

            public void CallsProtectedAbstractMethod()

            {

                var mocks = new MockRepository();

                var myObject = mocks.DynamicMock<MyAbstractClassTestWrapper>();

 

                myObject.Expect(m => m.DoSomethingSpecific()); // <= no more compile error

                myObject.Replay();

 

                myObject.DoSomethingInteresting();

                myObject.VerifyAllExpectations();

            }

        }

    }

I like it :)

11 Responses to “Mocking Dilemma, Solved!”

  1. Jan Van Ryswyck Says:

    One could also choose for the “self shunt” pattern, where the test fixture itself derives from the abstract base class. This has the disadvantage of being less readable when continuing to use Rhino Mocks for checking whether the abstract method is called. If simplicity is all you need, then no mocks are needed and a simple boolean member variable will do. If the scenario, is more complex, than this is a nice and clean solution.

    Kind regards,

    Jan

  2. den ben Says:

    Fantastic solution!

    But I’m wondering… wouldn’t it be enough to do it as follows:


    [TestFixture]
    public class MyAbstractClassTests : MyAbstractClass
    {
    [Test]
    public void CallsProtectedAbstractMethod()
    {
    var mocks = new MockRepository();
    var myObject = mocks.DynamicMock();

    myObject.Expect(m => m.DoSomethingSpecific()); // <= no more compile error

    myObject.Replay();

    myObject.DoSomethingInteresting();
    myObject.VerifyAllExpectations();
    }
    }

    Won’t this also work? And if not, what am i missing?

  3. den ben Says:

    ohw.. and the comment dit not allow me to post the
    var myObject = mocks.DynamicMock(); correctly

    you need to pass the MyAbstractClassTests type instead of the MyAbstractClassTestWrapper type

  4. Jan Van Ryswyck Says:

    @Den Ben: Kinda what I meant by using the “self shunt” pattern. Seeing the code and all, it looks nicer this way.

  5. den ben Says:

    @Jan: I see that now (sorry for not reading your comment in depth first). And that “self shunt” pattern wouldn’t even need a mock at all to be able to do the test (like you said)… which is probably what I would have done. However, I agree that Tom’s solution is the cleanest ;-)

  6. Davy Brion Says:

    letting the fixture inherit directly from the abstract class would require the fixture to implement the abstract method. which i didn’t like :)

  7. Jan Van Ryswyck Says:

    It wouldn’t matter for simple scenarios (e.g. on or two template methods). You can always hide the dirt behind a region :-). For more complex scenarios, Tom’s approach seems more feasible.

  8. Davy Brion Says:

    don’t get me started on regions ;)

  9. Rob Says:

    Moq has a support for protected methods. You can’t use lambdaexpressions with protected methods, but at least it’s supported.

  10. Dew Drop - July 22, 2008 | Alvin Ashcraft's Morning Dew Says:

    [...] Mocking Dilemma, Solved! (Davy Brion) [...]

  11. Davy Brion Says:

    don’t worry Rob, Moq is still on my TODO list :)

    along with a bunch of other things unfortunately :s

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>