On Apr 25, 2011, at 10:51 AM, Doug McInnes wrote: > Sure! > Here's the Gist: > > https://gist.github.com/940868 > > It's works in Rspec 2.5.1, but not in Rspec 1.3.2 > > Doug > > > On Apr 23, 2011, at 3:00 PM, David Chelimsky wrote: > >> On Apr 22, 2011, at 4:58 PM, Doug McInnes wrote: >> >>> Hi! >>> >>> I was just talking to @dchelimsky over Twitter about a weird corner case >>> we've run into on 1.3.1 (I've also been able to reproduce it in 1.3.2) >>> >>> So we're using this gem called ClassyStruct that's a higher performing >>> OpenStruct: >>> https://github.com/amikula/classy_struct >>> >>> Basically it acts the same as OpenStruct but defines methods on the >>> object's class instead of the object itself on the fly. >>> When it receives a call that hits method_missing it calls attr_accessor on >>> the method name then passes the call on to the object. >>> >>> Our problem comes from having one spec that stubs out a call to the object: >>> foo.stub! :bar => 'test' >>> >>> and later in another spec file trying to set the same method with a value >>> then having our code use that value: >>> # spec >>> foo.bar = 'other test' >>> # code >>> puts "#{foo.bar} baz" >>> >>> So our expectation is that foo.bar will return 'other test'. Instead it >>> hits the old stub on foo which calls method_missing which is picked up >>> again by ClassyStruct causing it to fire off attr_accessor again then >>> passing the method through causing the stub to call method_missing and on >>> and on finally giving us a "stack level too deep" error. >>> >>> The crux of the problem is that ClassyStruct is adding a method to the >>> class after Rspec has added the same method to the instance. >>> >>> As I said it's a very weird corner case because we're calling attr_accessor >>> on a class that already has objects floating around. The easiest way to fix >>> this is to use stub! in both places. >>> >>> Regardless we were surprised that the proxy sticks around after a test run. >>> What is the reason for keeping it around? >> >> There's no intent to keep it around, so there is a bug at play here, but >> let's see if we can narrow it down. >> >> Can you post (gist or pastie) an example that I can just run as/is to see >> the behavior you're seeing? >
Any ideas on this issue? Here's the code: class TestClass end # our use case is with a stub on a constant TEST = TestClass.new describe TestClass do it "works before the stub" do TestClass.send(:attr_accessor, :foo) TEST.foo = :baz TEST.foo.should == :baz TestClass.send(:remove_method, 'foo') TestClass.send(:remove_method, 'foo=') end it "has a stubbed method" do TEST.stub! :foo => :bar TEST.foo.should == :bar end it "fails after the stub" do TestClass.send(:attr_accessor, :foo) TEST.foo = :baz TEST.foo.should == :baz end end And the console output: ~/tmp $ ruby -v ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-darwin10.4.0] ~/tmp $ spec -v rspec 1.3.2 ~/tmp $ spec test.rb ..F 1) NoMethodError in 'TestClass fails after the stub' undefined method `foo' for #<TestClass:0x00000101180158> test.rb:28:in `block (2 levels) in <top (required)>' Finished in 0.046678 seconds 3 examples, 1 failure ~/tmp $ rspec -v 2.5.1 ~/tmp $ rspec test.rb ... Finished in 0.00154 seconds 3 examples, 0 failures As I said this is a weird corner case :) Thanks, Doug _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users