views:

101

answers:

2

I've been using RhinoMocks lately but I keep running into an issue. If I break into the debugger and step over code while a mock is in Record mode, I end up getting an exception along the lines of:

System.InvalidOperationException: Previous method 'SuchAndSuch.ToString();'  
requires a return value or an exception to throw.

But if I execute the same code without breaking into the debugger it will execute successfully and create the mock.

I'm pretty sure that the reason for this is that the debugger calls ToString() on objects to display them in the Locals and other Watch windows. But since the mock is in record mode RhinoMocks considers a call to ToString() to be a setup of expectations which then isn't completely correctly. Obviously this only happens with partial mocks on concrete classes. Mocks against interfaces do not exhibit this behavior.

Have other people run into this issue? Is there any simple remedy? Do other frameworks such as moq or TypeMock have this issue?

Thanks,

~ Justin

+3  A: 

I can remember having a similar issue with NMock many years ago. Basically, this problem occurs exactly because the debugger invokes and displays properties using the ToString method (unless you use DebuggerDisplayAttribute or similar).

This can be particularly problematic if you use strict mocks because they only allow you to invoke a member the specified number of times, and the debugger interferes with this. Using loose mocks addresses this (and many other) problems.

You may also want to move away from the record/playback mechanism of Rhino Mocks and begin using the newer and much better lambda syntax.

Moq uses lamda syntax (almost) exclusively, and I've never had such issues with it - but then again, I don't debug much these days, as unit tests have become a substitute to debugging.

Yet another remedy is simply to hide the Autos and Locals debugger windows.

Mark Seemann
Thanks for the info. I haven't seen the lambda syntax. Do you have a link for a good starting place to learn about it?
jkohlhepp
Here's the original announcement: http://ayende.com/Blog/archive/2008/05/16/Rhino-Mocks--Arrange-Act-Assert-Syntax.aspx
Mark Seemann
It's also commonly referred to as AAA syntax: http://ayende.com/Wiki/Rhino+Mocks+3.5.ashx
Mark Seemann
Thanks for the links. And regarding your potential solution I have not had success with just hiding Autos and Locals. I think the debugger is still executing ToString() even when they are hidden.
jkohlhepp
Accepted as answer. It doesn't directly address the heisenbug issue but it is an alternative.
jkohlhepp
A: 

As Mark suggested, this problem should go away if you stop using the record-replay-verify approach and start using stubs with the recommended AAA approach (arrange, act, assert) instead.

I've tried to explain the difference and how to do both with Rhino Mocks in this blog post.

Wim Coenen
To me, AAA does not contradict record-replay-verify; rather, it simply describes the overall organization of a test, any test, with or without the use of a mocking API. "Record-replay-verify" simply describes the organization of tests which use a behavior-oriented mocking API, where *expectations* can be recorded, then replayed, and finally verified.
Rogerio