以下のコード サンプルは、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
いくつか質問があります。
1) 作成と保存の両方のテストが mock_model を使用するため、let ブロックを使用する利点を理解しています。しかし、before ブロックの利点がわかりません。保存テストのみがスタブを必要とする場合、各テストの前に実行される before ブロックにコードを移動するのではなく、コードをテスト内に保持しないのはなぜですか?
2) より基本的には、before ブロックは作成テストが指定しているものに干渉しますか? 作成テストは、Message がいくつかのパラメーターで new を受け取る必要があることを示し、post :create でそれをテストします。しかし、before ブロックが単に new への呼び出しをスタブ化するだけの場合、作成テストで should_receive アサーションをショートさせませんか? おそらく、stub と should_receive がどのように相互作用するかを理解していません。