On Mon, Jul 7, 2008 at 2:28 AM, Sam Granieri, Jr <<a href="mailto:sam@samgranieri.com">sam@samgranieri.com</a>> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
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.<br>
<br>
I'm on edge rails and edge rspec.<br>
<br>
Datawise, a bar has_many suggested_beers, and a suggested_beer belongs to a bar<br>
<br>
suggested_beers_controller<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
class SuggestedBeersController < ApplicationController<br>
before_filter :find_bar<br>
<br>
#code omitted for brevity<br>
# GET /bars/1/suggested_beers/new<br>
def new<br>
@suggested_beer = @bar.suggested_beers.build<br>
<br>
respond_to do |format|<br>
format.html<br>
end<br>
end<br>
<br>
# POST /bars/1/suggested_beers<br>
def create<br>
@suggested_beer = @bar.suggested_beers.build(params[:suggested_beer])<br>
#more redaction<br>
end<br>
<br>
#code omitted for brevity<br>
private<br>
def find_bar<br>
@bar = Bar.find(params[:bar_id])<br>
end<br>
</blockquote>
<br>
<br>
<br>
suggested_beers_controller_spec.rb<br>
<br>
This is generated with rspec_scaffold, and i've added in the beer_id, bar_id, and ip_address attributes for stubbing.<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
def mock_suggested_beer(stubs={})<br>
stubs = {<br>
:save => true,<br>
:update_attributes => true,<br>
:destroy => true,<br>
:to_xml => '',<br>
:beer_id => "1",<br>
:bar_id => "1",<br>
:ip_address => "<a href="http://127.0.0.1" target="_blank">127.0.0.1</a>"<br>
}.merge(stubs)<br>
@mock_suggested_beer ||= mock_model(SuggestedBeer, stubs)<br>
end<br>
<br>
describe "responding to GET /bars/1/suggested_beers/new" do<br>
<br>
it "should succeed" do<br>
get :new, :bar_id => "1"<br>
response.should be_success<br>
end<br>
<br>
it "should render the 'new' template" do<br>
get :new, :bar_id => "1"<br>
response.should render_template('new')<br>
end<br>
<br>
it "should create a new suggested_beer" do<br>
SuggestedBeer.should_receive(:build).with().and_return(mock_suggested_beer)<br>
get :new, :bar_id => "1"<br>
end<br>
</blockquote>
"should create a new suggested_beer" fails with this message<br>
<br>
Spec::Mocks::MockExpectationError in 'SuggestedBeersController responding to GET /bars/1/suggested_beers/new should create a new suggested_beer'<br>
Mock 'SuggestedBeer_1016' received unexpected message :[]= with ("bar_id", 1)<br>
</blockquote><div><br>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.<br>
<br>In this case, assuming that your controller is setting up @bar in the obvious way, it would be something like. <br><br>it "should create a new suggested_beer" do<br> suggested_beers = mock("suggested_beers")<br>
bar = mock_model(Bar, :suggested_beers => suggested_beers)<br> Bar.stub!(:find).and_return(bar)<br> suggested_beer = mock_model(SuggestedBeer, ....)<br>
SuggestedBeer.should_receive(:build).with(:blatz)..and_return(mock_suggested_beer)<br>
get :new, :bar_id => "1", :suggested_beer => :blatz<br> end<br></div></div><br><br>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.<br>
<br>-- <br>Rick DeNatale<br><br>My blog on Ruby<br><a href="http://talklikeaduck.denhaven2.com/">http://talklikeaduck.denhaven2.com/</a>