Monday, November 12, 2012

RhinoMock AssertWasCalled vs GetArgumentsForCallsMadeOn

Someone once said something like: "Code is written once and read many times". That is why I propose not to use RhinoMocks' AssertWasCalled method for methods that accept parameters. Sure, it's written faster than using GetArgumentsForCallsMadeOn, but check out the error message you get for this:
string expectedMessage = "RhinoMocks baby!";
string actualMessage = "RhinoMocks dude!";
var fooMock = MockRepository.GenerateMock();

fooMock.Bar(actualMessage);

fooMock.AssertWasCalled(x => x.Bar(expectedMessage));
Your test will fail with the following message:
IFoo.Bar("RhinoMocks baby!"); Expected #1, Actual #0.
To fix this is actually a bit of a hassle. You have to debug the test and compare the parameters by hand. Replace the above with GetArgumentsForCallsMadeOn:
string expectedMessage = "RhinoMocks baby!";
string actualMessage = "RhinoMocks dude!";
var fooMock = MockRepository.GenerateMock();
fooMock.Bar(actualMessage);

var calls = fooMock.GetArgumentsForCallsMadeOn(x => x.Bar(string.Empty), o => o.IgnoreArguments());
Assert.AreEqual(1, calls.Count);
var arguments = calls[0];
Assert.AreEqual(expectedMessage, arguments[0]);
This is your failing test message now:
String lengths are both 16. Strings differ at index 11.
  Expected: "RhinoMocks baby!"
  But was:  "RhinoMocks dude!"
  ----------------------^
Much more readable and clear, no? * While you're actually making the error message more readable and not the code, I believe it falls into the same adage. Think about who's reading/using it afterwards (it might even be you!), not about taking shortcuts because it's less typing

2 comments:

Lodewijk said...

Nice! Didn't know this option. It also makes working with multiple arguments more readable (no endless list of Arg. things)

Peter said...

Indeed. Plus, it helps when checking arguments that were constructed at runtime.