-
-
Notifications
You must be signed in to change notification settings - Fork 357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pass the instance to any instance stubs. #351
Pass the instance to any instance stubs. #351
Conversation
Signed-off-by: Sam Phippen <samphippen@googlemail.com>
Changes Unknown when pulling 6287f7a on samphippen:pass-instance-to-any-instance-stubs into * on rspec:master*. |
Signed-off-by: Sam Phippen <samphippen@googlemail.com>
Now passes to should receive expectations too :) |
Changes Unknown when pulling a37e021 on samphippen:pass-instance-to-any-instance-stubs into * on rspec:master*. |
Signed-off-by: Sam Phippen <samphippen@googlemail.com>
Changes Unknown when pulling 4cb7c1a on samphippen:pass-instance-to-any-instance-stubs into * on rspec:master*. |
|
||
def pass_instance_to_any_instance_stubs=(arg) | ||
@pass_instance_to_any_instance_stubs = arg | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think yield_instance_from_any_instance_implementation_blocks
is a better name. What do you think?
This is a good start, but I think there's a simpler way to implement this:
I haven't worked out all the details of this alternate implementation, but it feels cleaner to me intuitively. Among other things, the code you added to |
|
||
after(:each) do | ||
RSpec::Mocks.configuration.pass_instance_to_any_instance_stubs = @orig_pass | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than putting this here, what do you think about creating a with isolated configuration
shared context? To me, isolating configuration seems like a cross-cutting concern we'll want to use elsewhere. Also, I recommend managing the isolation of the configuration by making that shared example group clear the RSpec::Mocks::Configuration
instance -- that way, it isolates any config change, as opposed to just this one config option. Thoughts?
What do you think about making the config option default to to For the 2.x => 3.0 upgrade, we can backport this to 2.99, with it defaulted to Thoughts? |
I like @myronmarston's plan, but won't it force most people to have to deal with this on upgrade? |
It'll only force those that use a block implementation with any_instance to do so. My impression is that that's not most users. Sent from my iPhone On Jul 11, 2013, at 3:58 AM, Jon Rowe notifications@github.com wrote:
|
…com/samphippen/rspec-mocks into pass-instance-to-any-instance-stubs
@myronmarston with edit: I was asking because I was having trouble getting my implementation working. This can be disregarded now unless you feel strongly against what I've implemented. |
Signed-off-by: Sam Phippen <samphippen@googlemail.com>
after do | ||
RSpec::Mocks.instance_variable_set(:@configuration, orig_configuration) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
honestly, I'd probably just set it to nil
in a before hook:
shared_context "with isolated configuration" do
before { RSpec::Mocks.instance_variable_set(:@configuration, nil) }
end
I think that's all you need, since the config is lazily initialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, scratch that. I wasn't thinking about the fact that we may want to change the config for our tests. Setting it to nil will blow those away. So nevermind.
stub.invoke(nil, *args, &block) | ||
elsif expectation | ||
if expectation.yield_receiver_to_implementation | ||
args.unshift(expectation.orig_object) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't feel like it belongs in mocks/proxy.rb
. Notice that you are asking expectation
something and then doing something with expectation.orig_object
. This is all knowledge that should be internal to MessageExpectation
. (And same with the stub
code above).
I think your concern here goes away once you move the BTW, we should make sure this doesn't interfere with |
@@ -0,0 +1,22 @@ | |||
require 'spec_helper' | |||
require 'pry' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you meant to leave this in ;)
…ions. Signed-off-by: Sam Phippen <samphippen@googlemail.com>
Signed-off-by: Sam Phippen <samphippen@googlemail.com>
@myronmarston I'm ok with defaulting this to true in 3.0 with the deprecation warning. Do you have any more code review on this implementation? |
@@ -173,6 +186,10 @@ def matches?(message, *args) | |||
|
|||
# @private | |||
def invoke(parent_stub, *args, &block) | |||
if yield_receiver_to_implementation_block? | |||
args.unshift(orig_object) | |||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One issue with doing it here is that this will caused the received to be passed to any message expectation implementation, not just a block implementation. For example, this will cause an extra arg to be passed when SomeClass.any_instance.should_receive(:foo).and_call_original
is used, which will break things, I think. I think you may want to wrap inner_implementation_action
w/ a proc that unshifts the args, and then forwards it on to the original proc. Thoughts?
Let's go with that then. If nothing else, changing it to |
Signed-off-by: Sam Phippen <samphippen@googlemail.com>
@myronmarston I made this the default, all the specs/cukes pass. I specifically wrote a spec to deal with and_call_original which seems to be passing. (not in the most recent commit) |
@yield_instance_from_any_instance_implementation_blocks = true | ||
end | ||
|
||
attr_accessor :yield_instance_from_any_instance_implementation_blocks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- It would be nice if this was a predicate, so that it's clear that it's a query message that returns true/false rather than a command method (the fact that it starts with
yield_...
makes it sound like a command). - On
MessageExpectation
, you phrased it asyield_receiver_to_implementation
, so for consistency, I'm thinking this should beyield_receiver_to_any_instance_implementation_blocks=
andyield_receiver_to_any_instance_implementation_blocks?
. I like using the wordreceiver
for the object (rather than usinginstance
twice in the name), and it's more accurate to say the receiver is yielded to the block rather than from the block.
Well done, @samphippen! I left a comment about the naming of the config option but this needs a changelog entry, but otherwise it's good to go. |
Signed-off-by: Sam Phippen <samphippen@googlemail.com>
Signed-off-by: Sam Phippen <samphippen@googlemail.com>
I'm going to go ahead and merge this, then (later today) squash this for 2-99 and turn the option off by default and make it issue a deprecation warning. |
…-stubs Pass the instance to any instance stubs.
Related to #175
This passes the instance for stubs, I'm not sure what to do for expectations: passing the instance breaks with. I'm going to continue to fiddle but wanted to get this out early to get feedback :)