The code samples below show a refactor from the chapter on controller specs in The RSpec Book:
require 'spec_helper'
describe MessagesController do
describe "POST create" do
it "creates a new message" do
message = mock_model(Message).as_null_object
Message.should_receive(:new).
with("text" => "a quick brown fox").
and_return(message)
post :create, :message => { "text" => "a quick brown fox" }
end
it "saves the message" do
message = mock_model(Message)
Message.stub(:new).and_return(message)
message.should_receive(:save)
post :create
end
it "redirects to the Messages index" do
post :create
response.should redirect_to(:action => "index")
end
end
end
require 'spec_helper'
describe MessagesController do
describe "POST create" do
let(:message) { mock_model(Message).as_null_object }
before do
Message.stub(:new).and_return(message)
end
it "creates a new message" do
Message.should_receive(:new).
with("text" => "a quick brown fox").
and_return(message)
post :create, :message => { "text" => "a quick brown fox" }
end
it "saves the message" do
message.should_receive(:save)
post :create
end
it "redirects to the Messages index" do
post :create
response.should redirect_to(:action => "index")
end
end
end
I have a couple of questions:
1) I understand the benefit of using the let block because the tests for both creation and save use the mock_model. However, I don't understand the benefit of the before block. If only the save test requires the stub, why not just keep the code in the test instead of moving it to a before block that runs before each test?
2) More fundamentally, does the before block interfere with what the creation test is specifying? The creation test says that Message should receive new with some parameters and then tests that with the post :create. But if the before block just stubs out the call to new, doesn't that short circuit the should_receive assertion in the creation test? Perhaps I'm not understanding how stub and should_receive interact.