Hey folks,
I’ve been mocking and stubbing pretty nicely after the various bits of
advice I received earlier about doing so. I’ve come to bits of code
that
work in one place and not in another, though. I’m hoping it’s not
something
simple I’ve missed. The code below fails even though code that is
practically the same elsewhere (except different models in use) passes.
What gives?
I have:
in notes_controller_spec.rb:
before(:each) do
@mock_note = mock_model(Note, :body => “The hot dog shipment will be
in
later tonight.”,
:organization => @mock_org)
@mock_org = mock_model(Organization, :name => “Slappy’s Hot Dog
Palace”,
:notes => [@mock_note])
@notes = [@mock_note]
end
it “should render ‘notes/new’ when the Note is setup with invalid data,
i.e.
without a body on POST create” do
Note.stub!(:new).and_return(@mock_note)
@notes.stub!(:<<).and_return(false)
post :create, :organization_id => @mock_org.id, :new_note => {
:body
=> @mock_note.body }
response.should render_template(“notes/new”)
end
in notes_controller.rb:
def create
@new_note = Note.new(params[:new_note])
respond_to do |wants|
if @organization.notes << @new_note
wants.html { redirect_to organization_url(@organization) }
else
wants.html { render :action => "new" }
end
end
end
I figured that my stubbing the << method out in the test to return false
would do the job of triggering the proper branch of the if statement in
the
controller action, but I’m not sure why it’s not doing so. I get the
error:
expected “notes/new”, got nil. I have code in my Users controller that
does
the exact same thing with the << method and the tests pass (they’re
virtually identical tests). Any thoughts? TIA.
–Tiffani AB
end
I figured that my stubbing the << method out in the test to return false would do the job of triggering the proper branch of the if statement in the controller action, but I’m not sure why it’s not doing so. I get the error: expected “notes/new”, got nil. I have code in my Users controller that does the exact same thing with the << method and the tests pass (they’re virtually identical tests). Any thoughts? TIA.
–Tiffani AB
Where in your create action are you defining @organization? is this
variable provided from a before filter? If not, that’s the first thing
you should look at. Another thing I noticed is that your @mock_note
defines its organization @mock_org before @mock_org is defined… thus
probably setting @mock_note.organization to nil.
On Mon, Jul 7, 2008 at 5:55 PM, Britt Mileshosky
[email protected]
wrote:
I’ve been mocking and stubbing pretty nicely after the various bits of
it “should render ‘notes/new’ when the Note is setup with invalid data,
i.e. without a body on POST create” do
Note.stub!(:new).and_return(@mock_note)
@notes.stub!(:< post :create, :organization_id => @
mock_org.id, :new_note => { :body => @mock_note.body }
response.should render_template(“notes/new”)
end
To add to what Britt already said, look at your example and then your
before
block again very carefully. Notice that you setup @notes in your before,
and
you use it to stub :<< in your example, but you never return @notes from
anything. Instead you setup @mock_org to return an array with
@mock_note.
Although the contents of this and @notes are the same, you have created
two
different arrays. You are probably wanting to be dealing with the same
@notes object in each of these cases.
Zach
I’m assuming RSpec 1.1.3+, but here’s how I might write this example:
describe NotesController do
it “renders ‘notes/new’ when an empty note is submitted” do
Note.stub!(:new).and_return(stub(“note”))
organization = stub_model(Organization, :notes => stub(“notes”,
:<< => false))
assigns[:organization] = organization
post :create, "organization_id" => organization.to_param,
“new_note” => { “body” => “” }
response.should render_template("notes/new")
end
end
I’m favoring the use of stub_model and stubs instead of mock_model
(and mocks) because we’re not setting any expectations on the note or
the organization. Rather, we’re just setting them up to deliver values
that are either simply required (as in Note.new returning something
non-nil) or what we want (the addition of the note to the organization
to fail).
I’ve also eliminated the idea of having existing notes on the
organization. It’s not central to what’s being spec’d, so it’s out.
Furthermore, I made the submitted note’s body empty because that’s
what was in the original description of the it block. That those two
didn’t match bothered me.
Finally, I simplified the description of the it block to what I
thought the essence of your example was; I hope that I’m at least
close.
Please let the list know if this helped or if you already revisited
the problem and solved it. I think we’re interested in what ends up
working for you.
Regards,
Craig
Hmmm…I made the changes that both you and Britt suggested and still no
dice. I broke it down and put print statements (yeesh) in the
controller
around the @organization.notes << @new_note statement. This confirms
that
the statement returns false just like the stub told it to do (so I took
out
the puts statement and ran the test again), but for some reason I still
don’t get the rendered template as set up in the else clause. I’m not
sure
what’s going on, but I suppose I’ll just skip that test until later.
Thanks for the help!
Tiffani AB
Yeah, I was on 1.1.4 and this solution with a few tweaks definitely
worked.
The original set up of my code called for having the Organization
returned
by the notes controller in a before filter, so I stubbed out this stuff
in
the before(:each) block. It ended up looking like this:
before(:each) do
@organization = stub_model(Organization, :name => “Slappy’s Hot Dog
Palace”)
Organization.stub!(:find).and_return(@organization)
end
Then, I followed Craig’s lead on what the example should do with a few
things taken out:
it “should render ‘notes/new’ when an empty note is submitted” do
Note.stub!(:new).and_return(stub(“note”))
post :create, :appointment_id => @appointment.id, :organization_id =>
@
organization.id, :new_note => { :body => “” }
response.should render_template(“notes/new”)
end
I kept the controller method just like it was in the original post. And
whoooo! Everything passed. I’ll be making sure I really differentiate
the
necessity of mock_model vs. stub_model from now on, too as a take-away
from
all this. Learning this stuff has really been interesting considering
months ago the only testing I was doing was making changes in Textmate
and
then clicking “Refresh” in a browser. lol.
Thanks again!
Tiffani AB
On Mon, Jul 7, 2008 at 10:31 PM, Craig D.
[email protected]
Whoops…wrong post.
should be
post :create, :organization_id => @organization.id, :new_note => { :body
=>
“” }
Copying from the wrong window…
Tiffani AB
On Tue, Jul 8, 2008 at 12:14 AM, Tiffani Ashley B.
[email protected]