Myron Marston
2010-Sep-20 00:08 UTC
[rspec-users] Behavior of object.foo(x) when you''ve stubbed it using object.stub(:foo).with(y)
The current behavior of rspec-mocks causes a NoMethodError when you
call object.foo(x) after setting up a stub using
object.stub(:foo).with(y). Here''s an example for when this has caused
me a problem:
- In a before(:each) block, I''ve setup a stub:
File.stub(:exist?).with("config.yml").and_return(false)
- The spec calls some library code that calls File.exist?
("results.yml")
- When this is called, a NoMethodError is raised due to the current
way rspec-mocks works.
David and I have been discussing this over on the issue tracker for
rspec-mocks[1]. I originally suggested that the stub should delegate
to the original method definition when it is called with a different
argument. David brought up that this has the potential to cause
problems for people that use stubbing to prevent something destructive
form occurring. Previously, object.stub(:foo).with(x) prevented the
real definition of foo from ever being called. A NoMethodError would
be raised when a different argument is passed, but you have the
guarantee that the real, potentially destructive, definition of foo
will never be invoked. My suggested change would allow the real
definition of foo to be called when a different argument is passed.
We''re considering adding an explicit way to allow the delegate to the
original definition (i.e. maybe another method on the fluent interface
that enables this).
I''m fine with this route, but I also feel like it''s a
sub-optimal
API. Just based on the naming of the API, I would expect `with` to
limit the scope of the stub so that it is only in effect when the
arguments match, and the original method definition to get used
otherwise. If you want a guarantee that a destructive method is never
invoked, you should probably just do object.stub(:foo), and not have a
`with`. But going this route does have the potential to cause
problems for people due to the existing behavior.
It''d be nice to get some feedback from other rspec-users on this.
Which way should we go with this? Please comment over on the github
issue tracker (linked to below) rather than here, so we keep the
discussion all in one place.
Thanks,
Myron
[1] http://github.com/rspec/rspec-mocks/issues/20
Justin Ko
2010-Sep-20 00:12 UTC
[rspec-users] Behavior of object.foo(x) when you''ve stubbed it using object.stub(:foo).with(y)
On Sep 19, 8:08?pm, Myron Marston <myron.mars... at gmail.com> wrote:> The current behavior of rspec-mocks causes a NoMethodError when you > call object.foo(x) after setting up a stub using > object.stub(:foo).with(y). ?Here''s an example for when this has caused > me a problem: > > - In a before(:each) block, I''ve setup a stub: > File.stub(:exist?).with("config.yml").and_return(false) > - The spec calls some library code that calls File.exist? > ("results.yml") > - When this is called, a NoMethodError is raised due to the current > way rspec-mocks works. > > David and I have been discussing this over on the issue tracker for > rspec-mocks[1]. ?I originally suggested that the stub should delegate > to the original method definition when it is called with a different > argument. ?David brought up that this has the potential to cause > problems for people that use stubbing to prevent something destructive > form occurring. ?Previously, object.stub(:foo).with(x) prevented the > real definition of foo from ever being called. ?A NoMethodError would > be raised when a different argument is passed, but you have the > guarantee that the real, potentially destructive, definition of foo > will never be invoked. ?My suggested change would allow the real > definition of foo to be called when a different argument is passed. > We''re considering adding an explicit way to allow the delegate to the > original definition (i.e. maybe another method on the fluent interface > that enables this). > > I''m fine with this route, but I also feel like it''s a sub-optimal > API. ?Just based on the naming of the API, I would expect `with` to > limit the scope of the stub so that it is only in effect when the > arguments match, and the original method definition to get used > otherwise. ?If you want a guarantee that a destructive method is never > invoked, you should probably just do object.stub(:foo), and not have a > `with`. ?But going this route does have the potential to cause > problems for people due to the existing behavior. > > It''d be nice to get some feedback from other rspec-users on this. > Which way should we go with this? ?Please comment over on the github > issue tracker (linked to below) rather than here, so we keep the > discussion all in one place. > > Thanks, > Myron > > [1]http://github.com/rspec/rspec-mocks/issues/20 > _______________________________________________ > rspec-users mailing list > rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-usersCan we get a tl;dr on this? ;-) j/k