[mocha-developer] counter-intuitive behaveour when passing a proc to Mocha::Expectation#returns

James Mead jamesmead44 at gmail.com
Thu Jan 11 07:36:08 EST 2007

On 11/01/07, Tomas Pospisek <tpo2 at sourcepole.ch> wrote:
> Let's say that I have a procedure that:
> * gets the number of bytes to write into some file
> * and returns the number of successfully written bytes
>    def save( text, len )
> This procedure is being used all over the place especially inside the
> method
> "process" which I want to test. Thus in order not to polute my filesystem
> I stub
> the "save" procedure. But of course in order for my "process" method I
> need the
> "save" procedure to return the correct number of bytes. Thus naively I'd
> do
> something like this:
>    stubs( :save ). returns( lambda { eval "len" } )
> Unfortunately this doesn't work, since the "stubs" method doesn't at all
> take
> parameter names into account. As far as I can see, this is the place where
> the
> actual method replacement is being done:
>    def define_new_method
>      stubbee.metaclass.class_eval "def #{method}(*args, &block)
>      mocha.method_missing(:#{method}, *args, &block); end"
>    end
> and it just passes all the arguments as an array. I'm not suggesting the
> fix for
> the problem at hand is trivial - I can't see at a glance how one can
> determine
> the signature of some method wrt to its parameter*names*, however from the
> Mocha-user's aka tester's perspective Mocha's behaveour is quite
> confusing.
> *t, exploring Mocha

Currently Mocha does not allow the Proc in returns() to have access to the
parameters passed into the stubbed method. Although it would be technically
possible, I don't think this is a good idea as it would allow you to add
behaviour to the stub. Stubs are all about canned responses (see
What you are talking about sounds more like a Fake Object.

If what you want to do is stub the 'save' method for your tests so that it
appears that files always get saved successfully, but nothing gets written
to the file-system - I'd be more inclined to define a fake version of the
class which have the desired implementation. This is what the 'test/mocks'
directory allows you to do in Rails. Alternatively you might be able to use
dependency injection to inject the fake version from your tests.

If you want a more detailed response, please post an example test and the
code under test.

More information about the mocha-developer mailing list