[rspec-devel] [ rspec-Bugs-11545 ] Rspec doesn't handle should_receive on ActiveRecord associations (r2094)

noreply at rubyforge.org noreply at rubyforge.org
Wed Jun 13 15:37:44 EDT 2007


Bugs item #11545, was opened at 2007-06-13 10:00
You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=3149&aid=11545&group_id=797

Category: mock module
Group: None
>Status: Closed
Resolution: Accepted
Priority: 3
Submitted By: Ian White (ianwhite)
Assigned to: Nobody (None)
Summary: Rspec doesn't handle should_receive on ActiveRecord associations (r2094)

Initial Comment:
The attached (standalone) spec should work, but fails on my machine (Mac OS X 10.4.9, rspec(_on_rails) r2094, rails r7006)

The spec:

class User < ActiveRecord::Base
  has_one :address, :as => :addressable

  delegate :postcode, :postcode=, :to => :address
end

class Address < ActiveRecord::Base
  belongs_to :addressable, :polymorphic => true
end

describe 'User with has_one :address' do
  before do
    @user = User.new
    @address = Address.new
    @user.address = @address
  end
  
  it { @user.should respond_to(:postcode=)}
  
  it 'address should repsond to :postcode=' do
    @address.should respond_to(:postcode=)
  end
  
  it 'should delegate :postcode to :address' do
    @address.should_receive(:postcode).with('foo').once
    @user.postcode = 'foo'
  end
  
  it { @user.should respond_to(:postcode=)} # same spec as above
  
  it 'address should repsond to :postcode=' do  # same spec as above
    @address.should respond_to(:postcode=)
  end  
end


produces:

..FFF

1)
NameError in 'User with has_one :address should delegate :postcode to :address (using should_receive)'
undefined method `postcode' for class `Address'
spec/specs/assoc_spec.rb:37:
spec/specs/assoc_spec.rb:23:

2)
NameError in 'User with has_one :address should respond to #postcode='
undefined method `proxied_by_rspec__postcode' for class `Address'
spec/specs/assoc_spec.rb:23:

3)
NameError in 'User with has_one :address address should repsond to :postcode='
undefined method `proxied_by_rspec__postcode' for class `Address'
spec/specs/assoc_spec.rb:23:

----------------------------------------------------------------------

Comment By: Ian White (ianwhite)
Date: 2007-06-13 15:14

Message:
No worries, glad to help.  Thanks for rspec!

----------------------------------------------------------------------

Comment By: David Chelimsky (dchelimsky)
Date: 2007-06-13 15:13

Message:
Latest patch applied to r2096.

Nicely done. Thanks!

----------------------------------------------------------------------

Comment By: Ian White (ianwhite)
Date: 2007-06-13 14:58

Message:
the resubmitted patch is a little cleaner (the top one in
the list at the bottom)

----------------------------------------------------------------------

Comment By: Ian White (ianwhite)
Date: 2007-06-13 14:58

Message:
Bugger - I misspelt receive ("i after e except before c" -
it just didn't stick in spelling class...) in the spec 

----------------------------------------------------------------------

Comment By: Ian White (ianwhite)
Date: 2007-06-13 14:53

Message:
Hi David,

Attached is diff which specs the problem (methods don't get
cleaned up on classes because their metaclass sticks around)

in the diff is the fix.

This is my first rspec patch - not sure if that random token
stuff is supposed to be there.

Awesomely comprehensive pre_commit script by the way!

----------------------------------------------------------------------

Comment By: David Chelimsky (dchelimsky)
Date: 2007-06-13 14:23

Message:
Mine was less code. Not necessarily cleaner. If you want, please re-submit diff against the new trunk (2095). The spec I added is in rspec/spec/mocks/bug_report_11545.rb. Please add your additional examples (dealing w/ method count) there.

Thx

----------------------------------------------------------------------

Comment By: Ian White (ianwhite)
Date: 2007-06-13 14:17

Message:
I see it at the bottom...

the url is
http://rubyforge.org/tracker/download.php/797/3149/11545/2095/proxy.diff

Yours was cleaner - but I'm worried that yours won't undef
method counting method in cleanup - I'm just writing a spec
now to be sure. 

----------------------------------------------------------------------

Comment By: David Chelimsky (dchelimsky)
Date: 2007-06-13 14:14

Message:
Ian - I don't see the diff attached. Feel free to attach it - I'd like to see what you came up w/.

Thx



----------------------------------------------------------------------

Comment By: David Chelimsky (dchelimsky)
Date: 2007-06-13 14:10

Message:
Fixed in r2095.

----------------------------------------------------------------------

Comment By: Ian White (ianwhite)
Date: 2007-06-13 13:50

Message:
Wow, that was quick!

I had just started to go down that path - attached is a diff
that makes the spec pass - I've not yet tested the entire
rspec suite, doing that next

----------------------------------------------------------------------

Comment By: David Chelimsky (dchelimsky)
Date: 2007-06-13 13:23

Message:
I've found the problem.

RSpec asks the object if it responds_to?(:postcode=), to which AR says "yes", at which point RSpec tries to proxy the method by aliasing it and redefining the original. The problem is that there is no original at that point. AR is telling the truth, in that the object will respond_to(:postcode=), but it does it by implementing the method the first time it gets called.

Looking into a fix.

----------------------------------------------------------------------

Comment By: Ian White (ianwhite)
Date: 2007-06-13 13:16

Message:
That's fair enough.

I'll start digging.  I'm guessing it has something to do
with the Rails Association Proxy getting in the way of the
RSpec Mock proxy (if you know that's not it - let me know).

----------------------------------------------------------------------

Comment By: Aslak Hellesøy (aslak_hellesoy)
Date: 2007-06-13 12:31

Message:
It depends what you mean by "on the agenda". There are several other issues in the tracker and I cannot give you an ETC for this one. If you want this fixed quickly I encourage you to submit a patch.

----------------------------------------------------------------------

Comment By: Ian White (ianwhite)
Date: 2007-06-13 11:29

Message:
Thanks for the quick response.

Can you confirm that fixing this is on the agenda?  Or
should I be moving to mocha for everything?

----------------------------------------------------------------------

Comment By: Aslak Hellesøy (aslak_hellesoy)
Date: 2007-06-13 10:50

Message:
First, there is a bug in your 3rd spec's should_receive. It should use should_receive(:postcode=) instead of should_receive(:postcode)

I was able to reproduce your problem. I can confirm it's due to a bug in RSpec's mock framework and I don't have a fix for it now.

I tried to use mocha instead (just use expects instead of should_receive), and all specs passed. I recommend you use mocha until this is fixed.

----------------------------------------------------------------------

You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=3149&aid=11545&group_id=797


More information about the rspec-devel mailing list