[rspec-users] Trouble with Association Proxies and new/create in rails

Rick DeNatale rick.denatale at gmail.com
Mon Jul 7 16:20:35 EDT 2008


On Mon, Jul 7, 2008 at 2:28 AM, Sam Granieri, Jr <sam at samgranieri.com>
wrote:

> I'm working on some code that uses association proxies. I'm trying to get
> away from using fixtures, and move more to mocking and stubbing. So far, so
> good, but the methods I cant figure out, even with extensive googling, are
> how to simulate the association_proxy.build method in rails.
>
> I'm on edge rails and edge rspec.
>
> Datawise, a bar has_many suggested_beers, and a suggested_beer belongs to a
> bar
>
> suggested_beers_controller
>
>  class SuggestedBeersController < ApplicationController
>>  before_filter :find_bar
>>
>>  #code omitted for brevity
>>  # GET /bars/1/suggested_beers/new
>>  def new
>>    @suggested_beer = @bar.suggested_beers.build
>>
>>    respond_to do |format|
>>      format.html
>>    end
>>  end
>>
>>   # POST /bars/1/suggested_beers
>>  def create
>>    @suggested_beer = @bar.suggested_beers.build(params[:suggested_beer])
>>    #more redaction
>>  end
>>
>>  #code omitted for brevity
>>  private
>>  def find_bar
>>    @bar  = Bar.find(params[:bar_id])
>>  end
>>
>
>
>
> suggested_beers_controller_spec.rb
>
> This is generated with rspec_scaffold, and i've added in the beer_id,
> bar_id, and ip_address attributes for stubbing.
>
>   def mock_suggested_beer(stubs={})
>>    stubs = {
>>      :save              => true,
>>      :update_attributes => true,
>>      :destroy           => true,
>>      :to_xml     => '',
>>      :beer_id    => "1",
>>      :bar_id     => "1",
>>      :ip_address => "127.0.0.1"
>>    }.merge(stubs)
>>    @mock_suggested_beer ||= mock_model(SuggestedBeer, stubs)
>>  end
>>
>>  describe "responding to GET /bars/1/suggested_beers/new" do
>>
>>    it "should succeed" do
>>      get :new, :bar_id => "1"
>>      response.should be_success
>>    end
>>
>>    it "should render the 'new' template" do
>>      get :new, :bar_id => "1"
>>      response.should render_template('new')
>>    end
>>
>>    it "should create a new suggested_beer" do
>>
>>  SuggestedBeer.should_receive(:build).with().and_return(mock_suggested_beer)
>>      get :new, :bar_id => "1"
>>    end
>>
> "should create a new suggested_beer" fails with this message
>
> Spec::Mocks::MockExpectationError in 'SuggestedBeersController responding
> to GET /bars/1/suggested_beers/new should create a new suggested_beer'
> Mock 'SuggestedBeer_1016' received unexpected message :[]= with ("bar_id",
> 1)
>

The way I approach this is to stub the object which has the association
proxy to return a mock for the proxy.  To do that you have to stub whatever
method your controller uses to get that object.

In this case, assuming that your controller is setting up @bar in the
obvious way, it would be something like.

it "should create a new suggested_beer" do
     suggested_beers = mock("suggested_beers")
     bar = mock_model(Bar, :suggested_beers => suggested_beers)
     Bar.stub!(:find).and_return(bar)
     suggested_beer = mock_model(SuggestedBeer, ....)

 SuggestedBeer.should_receive(:build).with(:blatz)..and_return(mock_suggested_beer)
     get :new, :bar_id => "1", :suggested_beer => :blatz
 end


Some would break this down into at least two examples, one just checking
that the build method is called and another checking that it is called with
the expected paramenters.

-- 
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20080707/217f73a4/attachment-0001.html>


More information about the rspec-users mailing list