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 ![]()
July 22nd, 2008 at 9:08 am
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
July 22nd, 2008 at 11:47 am
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?
July 22nd, 2008 at 11:50 am
ohw.. and the comment dit not allow me to post the
var myObject = mocks.DynamicMock();correctlyyou need to pass the MyAbstractClassTests type instead of the MyAbstractClassTestWrapper type
July 22nd, 2008 at 12:02 pm
@Den Ben: Kinda what I meant by using the “self shunt” pattern. Seeing the code and all, it looks nicer this way.
July 22nd, 2008 at 12:21 pm
@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
July 22nd, 2008 at 12:37 pm
letting the fixture inherit directly from the abstract class would require the fixture to implement the abstract method. which i didn’t like
July 22nd, 2008 at 12:52 pm
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.
July 22nd, 2008 at 12:55 pm
don’t get me started on regions
July 22nd, 2008 at 1:43 pm
Moq has a support for protected methods. You can’t use lambdaexpressions with protected methods, but at least it’s supported.
July 22nd, 2008 at 2:00 pm
[...] Mocking Dilemma, Solved! (Davy Brion) [...]
July 22nd, 2008 at 2:48 pm
don’t worry Rob, Moq is still on my TODO list
along with a bunch of other things unfortunately :s