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