1

我对 rspec 和inherited_resources 都是新手。我有一个简单的资源,联系人,它有一个名称字段。控制器没有特殊功能。

class ContactsController <  InheritedResources::Base 
  actions :all, :except => [:show]
end

我已经使用 mock_model 编写了创建和索引的规范。但是,在更新时使用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。

我究竟做错了什么?

4

1 回答 1

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.
于 2011-05-09T23:26:34.487 回答