在rspec中传递形式参数

时间:2012-01-05 19:49:00

标签: ruby-on-rails-3.1 rspec2

我正在使用acts_as_audited。在destroy操作的控制器中,我传递了审计注释值。所有这一切都运作良好,但当我尝试测试我得到的销毁动作时:

PurchasesController DELETE /destroy deletes the correct Purchase
 Failure/Error: delete :destroy, id: i
 NoMethodError:
  You have a nil object when you didn't expect it!  
  You might have expected an instance of Array.  
  The error occured while evaluating nil.[] 
# ./app/controllers/purchases_controller.rb:79:in `destroy'
# ./spec/controllers/purchases_controller_spec.rb:156:in `block (3 levels) in <top (required)>'

第79行读取:@purchase.audit_comment = params[:purchase][:audit_comment]

继承我的代码:

PurchasesController

def destroy
  @purchase = Purchase.find(params[:id])
  @purchase.audit_comment = params[:purchase][:audit_comment]
  respond_to do |format|
    if @purchase.destroy
      format.html { redirect_to(purchases_url, notice: "Successfully destroyed purchase.") }
      format.xml  { render :xml => @purchase, :status => :deleted, :location => @purchase }
    else
      flash[:alert] = "#{@purchase.po_number} could not be destroyed"
      render 'show'
    end
  end
end

购买show.html.erb 已编辑

<%= form_for @purchase, method: :delete do |builder| %>

<% if @purchase.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@purchase.errors.count, "error") %> prohibited this purchase from being saved:</h2>

    <ul>
    <% @purchase.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>

<% title "Purchase" %>

<div id="delete_button">    
  <span><strong>PO Number:  <%= @purchase.po_number %></strong></span>
    <%= render "audit_comment", f: builder %>
    <%= builder.submit "Destroy Purchase"%>
</div>  
<% end %>
<p>
  <%= link_to "Edit", edit_purchase_path(@purchase) %> |
  <%= link_to "View All", purchases_path %>
</p>

_audit_comment.html.erb - 购买

<div id = "audit">
  <%= f.label :audit_comment %>:<br />
  <%= f.text_area :audit_comment, :size => "60x5" %>
</div>

purchase_controller_spec.rb

require 'spec_helper'
require 'ruby-debug'

describe PurchasesController do
  login_user
  render_views

  before(:each) do
    @purchase = Factory(:purchase)
  end

  describe "DELETE /destroy" do
    before(:each) do
      @ability.can :destroy, Purchase      
    end  
    it "deletes the correct Purchase" do
      i = @purchase.id
      c = Purchase.count
      pl = Purchase.find(i).purchase_line_items
      cpl = pl.count
      delete :destroy, id: i
      Purchase.count.should == c-1
      pl.count.should == cpl-1
      response.should redirect_to(purchases_path)
      flash[:notice].should == "Successfully destroyed purchase."
    end
    it "redirects to the index page with an alert when a delete fails" do
      i = @purchase.id
      c = Purchase.count
      pl = Purchase.find(i).purchase_line_items
      cpl = pl.count
      Purchase.any_instance.stubs(:valid?).returns(:false)
      delete :destroy, id: i
      Purchase.count.should_not == c-1
      pl.count.should_not == cpl-1
      response.should render_template('show')
      flash[:alert].should == "#{@purchase.po_number} could not be destroyed"
    end
  end
end

感谢任何帮助。谢谢!

1 个答案:

答案 0 :(得分:2)

它告诉你,在第79行,params[:purchase]是零。

它的原因是button_to生成自己的表单标记。因此,您现在<form>内有<form>,并且您的审核评论字段未提交。您应该使用button_to而不是builder.submit。您还需要在致电:method时设置form_for选项,以使其成为DELETE请求。

修改后更新

HTML现在看起来不错,但我发现规范存在问题。我想您忘记将审核评论传递给您的HTTP参数。它存在于HTML中,但是您的规范会绕过表单,因为它会单独测试控制器。 (集成测试将使用实际形式。控制器测试不会。)因此,您必须手动将任何形式的控制器期望的参数添加到请求中。例如:

delete :destroy, :id => 1, :purchase => {:audit_comment => 'Test comment'}