我是rspec和inherited_resources的新手。我有一个简单的资源,Contact,它有一个名字字段。控制器没有特殊功能。
class ContactsController < InheritedResources::Base
actions :all, :except => [:show]
end
我使用mock_model为create和index编写了很好的规范。但是,在更新时使用mock_model时,在放置时无法找到联系人。所以,我转而使用真实模型:
describe "PUT update" do
let(:contact) { Contact.create(:name => "test 1") }
it "edits the contact" do
contact.name = "#{contact.name}-edited"
end
context "when the contact updates successfully" do
before do
contact.stub(:save).and_return(true)
end
it "redirects to the Contacts index" do
put :update, :id => contact.id, :contact => contact
#assigns[:contact].name = "test 1 - edited"
response.should redirect_to(:action => "index")
end
end
context "when the contact fails to save" do
before do
contact.stub(:save).and_return(false)
contact.stub(:update_attributes).and_return(false)
contact.stub(:errors).and_return(:errors => { :anything => "anything" })
end
it "renders the edit template" do
put :update, :id => contact.id, :contact => contact
response.should render_template :edit
end
end
end
我收到以下错误:
Failures:
1) ContactsController PUT update when the contact fails to save renders the edit template
Failure/Error: response.should render_template :edit
Expected block to return true value.
# ./spec/controllers/contacts_controller_spec.rb:82:in `block (4 levels) in <top (required)>'
当我检查status_code时,它是302重定向到/ contacts /:id。
我做错了什么?
答案 0 :(得分:3)
当人们开始在控制器测试中使用模拟时,这是一个非常常见的问题。你是在规范本地的对象上存根方法。当您使用put
访问控制器时,InheritedResources正在调用Contact.find(params[:id])
并返回自己的对象,不是您想要的对象。
您的规范失败,因为update_attributes
无问题地运行,并重定向回对象的show
页面。
对此的一般修复是模拟模型上的find
方法,以便它返回您的存根对象而不是另一个。
Contact.should_receive(:find).and_return(contact)
contact.should_receive(:update_attributes).and_return(false)
put :update, :id => contact.id, # etc.