[rspec-devel] [ rspec-Bugs-8302 ] Strange side effect when mocking a class method

noreply at rubyforge.org noreply at rubyforge.org
Tue Jan 30 18:27:51 EST 2007

Bugs item #8302, was opened at 2007-01-30 02:35
You can respond by visiting: 

Category: mock module
Group: None
Status: Closed
Resolution: Accepted
Priority: 3
Submitted By: Tobias Grimm (e-tobi)
Assigned to: David Chelimsky (dchelimsky)
Summary: Strange side effect when mocking a class method

Initial Comment:

This one is really driving me mad:

    class Foo
        def Foo.bar(arg)

    context "Context" do
        specify "spec 1" do

        specify "spec 2" do

Running these specs results in this failure:

    ArgumentError in 'Context 1 spec 1.2'
    wrong number of arguments (0 for 1)
    ./xxx_controller_spec.rb:14:in `bar'
    ./xxx_controller_spec.rb:14:in `bar'

    Finished in 0.002342 seconds

If I comment out the mocking of bar() in spec 1 it works. If I pass a string instead of an empty array in spec 1.2 it works too. I also can add a default value for the arg parameter in bar() and it will work. But in the above constellation, it doesn't work.

Maybe there's something going wrong with the define_method() call in the MockHandler class, that puts the original method of the mocked class back in place. This might also be a Ruby bug - I'm not sure.

Any ideas?




>Comment By: Tobias Grimm (e-tobi)
Date: 2007-01-30 23:27

Thanks a million! I've tested the last revision and it works
fine now!


Comment By: David Chelimsky (dchelimsky)
Date: 2007-01-30 22:34

Turns out that this is a problem for instance methods as well - we just never noticed it because typically each spec is dealing with its own instances.

Whether or not this is a Ruby bug is hard to say. We had been storing proxied methods in a Hash w/ the method name as a key and then restoring them back to the object.

The fix, which inadvertently also fixed bug 7611, was to use alias_method on the way in and out. In other words, based on your example above, when you call:


the MockHandler is now aliasing :bar with :bar__proxied_by_rspec (using alias_method, so it actually makes a copy) and redefining :bar to intercept calls.

When the spec is over, the alias is reversed and the munged name is removed.

Fixed in rev 1447


You can respond by visiting: 

More information about the rspec-devel mailing list