[rspec-users] mock libraries, Object#send, and Object#__send__

Scott Taylor mailing_lists at railsnewbie.com
Thu Dec 6 17:22:14 EST 2007


On Dec 6, 2007, at 5:12 PM, David Chelimsky wrote:

> On Dec 6, 2007 4:08 PM, Scott Taylor  
> <mailing_lists at railsnewbie.com> wrote:
>>
>> On Dec 6, 2007, at 4:41 PM, David Chelimsky wrote:
>>
>>> On Dec 6, 2007 3:37 PM, Scott Taylor
>>> <mailing_lists at railsnewbie.com> wrote:
>>>>
>>>>
>>>> What is the appropriate way to stub out (and put an expectation on
>>>> Object#__send__), without getting warnings from the Rspec mock
>>>> library?
>>>
>>> Come on Scott - you know better than that :)
>>>
>>> Error please?
>>
>> Not an error, just a warning.  And I should have written my
>> description better.  Basically, I wanted to make sure that my library
>> didn't call send, but instead __send__.  I tried something like this:
>>
>>     before :each do
>>        @caller = Object.new
>>        @caller.stub!(:send).and_raise
>>        @caller.stub!(:__send__)
>>
>>      end
>>
>>      it "should be able to send the message with __send__" do
>>        @caller.should_not_receive(:send)
>>        @caller.should_receive(:__send__)
>>
>>        @attributes.to_new_class_instance({}, @caller)
>>      end
>>
>>
>> The @caller object is a sort of mock object.  I would have used a
>> real mock object, except that stubbing send on a mock object didn't
>> seem to do anything.
>>
>> The warning was this:
>>
>> ./usr/local/lib/ruby/gems/1.8/gems/rspec-1.0.8/lib/spec/mocks/
>> proxy.rb:99: warning: redefining `__send__' may cause serious problem
>
> I LOVE that it says "may cause serious problem" - not "problems"
>
> Anyhow - I'm not sure what we can do about that. RSpec's stubs work by
> redefining existing methods. Ruby doesn't want you to do that with
> __send__. For the moment, there's no way around it, but I'm not even
> sure what we could change in RSpec to make it work. Any ideas?

Ah - so it's actually something ruby does, and not the mock library.   
I hadn't realized that.

I'm not sure this is the best idea, but we could actually remove the  
warning:

     def execute_silently(&blk)
       old_warning_level = $VERBOSE
       $VERBOSE = nil
       yield
       $VERBOSE = old_warning_level
     end


(or I could do this myself, in my own specs)

Scott



More information about the rspec-users mailing list