【问题标题】:Rspec & Rails: Testing create action with invalid attributesRspec & Rails:测试创建具有无效属性的操作
【发布时间】:2014-06-28 06:34:04
【问题描述】:

我正在为 Rspec 中的 Rails 编写我的第一个控制器测试。在测试 create 操作时,我想编写一个测试来验证在提交带有无效属性的表单时是否呈现了“新”模板。在这种情况下,这意味着一个字段是空白的。

我找到了几个我尝试逐字逐句遵循的示例。但是,当使用 Rspec 触发创建操作时,似乎 ActiveRecord 实际上会尝试创建由于验证而失败的记录。因此,在我测试重定向功能之前,我的测试就失败了。对于编写教程或 StackOverflow 答案的人来说,这似乎不是问题。

在给定无效属性的情况下,在控制器中测试创建操作的最佳方法是什么?

Rails 4.0.0、Ruby 2.0.0、Rspec 3.0.0.beta2

order_items_controller_spec

describe "POST create" do
    context "with invalid attributes" do
        it "re-renders the new method" do
            post :create, order_item: FactoryGirl.attributes_for(:order_item, :buyer_id => nil)
            expect( response ).to render_template :new
        end
    end
end

order_items_controller

def create
    @order_item = OrderItem.new(order_item_params)
    respond_to do |format|
        if @order_item.save!
            format.html { redirect_to cart_path(@order_item), notice: 'Your trip has been added to your cart.' }
            format.json { render action: 'show', status: :created, location: @order_item }
        else
            format.html { redirect_to new_order_item_path, notice: 'We were unable to customize your trip.' }
            format.json { render json: @order_item.errors, status: :unprocessable_entity }
        end
    end
end

rspec 错误信息:

 OrderItemsController POST create with invalid attributes re-renders the new method
     Failure/Error: post :create, order_item: FactoryGirl.attributes_for(:order_item, :buyer_id => nil)
     ActiveRecord::RecordInvalid:
     Validation failed: Buyer can't be blank
    # ./app/controllers/order_items_controller.rb:30:in `block in create'
    # ./app/controllers/order_items_controller.rb:29:in `create'
    # ./spec/controllers/order_items_controller_spec.rb:43:in `block (4 levels) in <top (required)>'

提前致谢。

【问题讨论】:

    标签: ruby-on-rails rspec


    【解决方案1】:

    你的测试看起来不错;实际上,当保存失败时,您的代码无法按预期工作。当您说“ActiveRecord 实际上尝试创建由于验证而失败的记录”时,这正是您希望测试执行的操作,因为您正在尝试测试如果验证失败会发生什么.

    在您的控制器中,您将使用save! 保存记录。如果保存失败,这将导致引发错误,这就是为什么您会立即在 rspec 中看到失败,而不是继续查看 new 视图。

    相反,您想使用save(没有爆炸声)。这将根据保存成功返回真/假,因此您可以在条件下使用它。

    你的控制器代码应该是:

    def create
        @order_item = OrderItem.new(order_item_params)
        respond_to do |format|
            if @order_item.save    ### ! removed
              ...
    

    【讨论】:

    • 就是这样,谢谢。我认为提出错误是一种最佳做法。为什么我在这里错了?有没有这方面的资源可以指导我?
    • 这与正确或错误无关,只是一种捕获保存失败的不同方法。通常测试真/假条件更容易,因此您想使用.save 方法。如果您更喜欢使用begin/rescue 捕获错误的方法,请使用.save! 方法。我发现在控制器中使用 true/false 更合乎逻辑。但是,如果我正在创建一个测试场景(例如在黄瓜步骤中),我想立即看到失败,所以我使用 .save!。有关更多信息,请参阅 Rails 指南:guides.rubyonrails.org/v3.2.13/…
    【解决方案2】:

    不要使用“保存!” ...您应该使用“保存”,如果无效,它将返回 false。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多