How to override rspec-mock's receive method for extension gem?

311 views
Skip to first unread message

George Mendoza

unread,
Jul 23, 2013, 6:22:33 AM7/23/13
to rs...@googlegroups.com
Hello everybody,

I'm trying to update my rspec extension gem (https://github.com/gsmendoza/verified_double) to the new expect syntax of rspec-mocks. I guessed that I can do this by creating a thin wrapper over the expect, receive, and allow methods of RSpec::Mocks::Syntax:


    module VerifiedDouble
      module RSpecMocksSyntaxOverrides
        def expect(*args)
          VerifiedDouble.registry.current_double = args[0]
          super(*args)
        end

        def receive(*args)
          VerifiedDouble.registry.add_method_signature_with_current_double(args[0])
          super(*args).tap {|result| result.extend(VerifiedDouble::CanRecordInteractions) }
        end
      end
    end

The test for overridden expect method passes, but the test for the receive method fails. If I rename my receive method to something else like better_receive, then the test suite can pick it up.

If you can point me where or how to integrate the VerifiedDouble::RSpecMocksSyntaxOverrides module, that would be a big help :)

Thank you very much,

George Mendoza
Philippines



David Chelimsky

unread,
Jul 23, 2013, 7:43:35 AM7/23/13
to rs...@googlegroups.com
I cloned the repo, checked out the branch, ran rspec and got the following error:

undefined method `add_method_signature_with_current_double' for #<VerifiedDouble::RecordedMethodSignatureRegistry:0x007f9cdab73f58>

Then I grepped through the code and I don't see any add_method_signature_with_current_double method, so the error seems legit to me. I might be missing something (like a `method_missing` designed to handle this) but maybe that helps point you in the right direction.

HTH,
David

David Chelimsky

unread,
Jul 23, 2013, 7:57:21 AM7/23/13
to rs...@googlegroups.com
Just realized I ran that using rspec-2.13 :)

Please disregard.

As a general FYI, please include the failure message when asking for help instead of just saying that it failed. Had I seen the error message was different from mine I wouldn't have wasted your time or mine w/ my previous response.

David Chelimsky

unread,
Jul 23, 2013, 8:20:51 AM7/23/13
to rs...@googlegroups.com
I think I found part of the problem: receive is defined by rspec-mocks when the configuration is eval'd and `enable_expect` is invoked: https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/syntax.rb#L87

That happens after all the requires, therefore verified-double's version of `receive` is defined _before_ rspec's version. You'll need a way to ensure verified-double's version gets defined after rspec's version.

@myronmarston - any thoughts on the best way to do that ^^?

That, plus I still don't see add_method_signature_with_current_double anywhere in the code, so that might still be a problem.

HTH,
David

Myron Marston

unread,
Jul 23, 2013, 11:12:24 AM7/23/13
to rs...@googlegroups.com
Yeah, we've had to do some slightly non-standard things to make the syntax configurable.  David, you mention it happening after all the requires, but when `rspec/mocks/configuration.rb` is required it configures it:


These sorts of things usually come down to the order of modules/classes in the ancestors chain, and one difference between `expect` and `receive` is that `expect` is defined in rspec-expectations in the RSpec::Matchers module:


...whereas `receive` is defined in rspec-mocks in the RSpec::Mocks::ExampleMethods module:


So, it sounds like your module is being inserted between these two modules, such that it can override one method, but not the other.  Maybe you can change the way you are including your module so that it winds up at the right place in the ancestors chain?  You can inspect it by putting `p self.class.ancestors` inside an example.

HTH,
Myron

George Mendoza

unread,
Jul 26, 2013, 5:35:05 AM7/26/13
to rs...@googlegroups.com
Hi Myron, David,

Thanks for the replies. I thought I posted a reply a few days ago, but it seems I clicked the wrong button :p

Anyway, I was able to override the receive method by extending the ExampleGroup instance in a before callback (https://github.com/gsmendoza/verified_double/blob/master/lib/verified_double/rspec_configuration.rb#L4-L6). I don't know if this is inefficient way to extend the example group, but on the plus side, it's quite simple and it doesn't involve tinkering with RSpec's internals.

Sorry about not providing the failure messages in the first post. Yeah, should have added those..

Thanks very much!

George
Reply all
Reply to author
Forward
0 new messages