【问题标题】:Rails / AR – how to test ::update(id, attributes) in rspecRails / AR – 如何在 rspec 中测试 ::update(id, attributes)
【发布时间】:2015-10-06 12:11:38
【问题描述】:

我正在使用活动记录update 方法更新多条记录,每条记录都有自己的属性。

我通过这个控制器代码(有效)促进了这一点:

def update
  keys = params[:schedules].keys
  values = params[:schedules].values
  if Schedule.update(keys, values)
    flash[:notice] = "Schedules were successfully updated."
  else
    flash[:error] = "Unable to update some schedules."
  end
  respond_to do |format|
    format.html { redirect_to responsibilities_path }
  end
end

我的问题是,如何在不访问 rspec 中的数据库的情况下进行测试

这是我正在尝试的,但它不起作用。

describe "PATCH update" do

  it "updates the passed in responsibilities" do
    allow(Schedule)
      .to receive(:update)
      .with(["1", "2"], [{"status"=>"2"}, {"status"=>"1"}])
      .and_return(true)
    # results in
    # expected: 1 time with arguments: (["1", "2"], [{"status"=>"2"}, {"status"=>"1"}])
    # received: 0 times
    # Couldn't find Schedule with 'id'=1

    # without the allow, I get
    # Failure/Error: patch :update, schedules: {
    # ActiveRecord::RecordNotFound:
    #   Couldn't find Schedule with 'id'=1
    # # ./app/controllers/responsibilities_controller.rb:18:in `update'
    # # ./lib/authenticated_system.rb:75:in `catch_unauthorized'
    # # ./spec/controllers/responsibilities_controller_spec.rb:59:in `block (5 levels) in <top (required)>'

    patch :update, schedules: {
      "1" => {
        "status" => "2",
      },
      "2" => {
        "status" => "1",
      }
    }
    expect(Schedule)
      .to receive(:update)
      .with(["1", "2"], [{"status"=>"2"}, {"status"=>"1"}])
    expect(flash[:error]).to eq(nil)
    expect(flash[:notice]).not_to eq(nil)
  end
end

我使用的是 Rails 4.2.4 和 rspec 3.0.0

【问题讨论】:

    标签: ruby-on-rails activerecord rspec


    【解决方案1】:

    你的问题是,你所期望的

    expect(Schedule)
          .to receive(:update)
          .with(["1", "2"], [{"status"=>"2"}, {"status"=>"1"}])
          .and_call_original     
    

    调用补丁方法后。

    这意味着请求在断言建立之前到达您的控制器。 要解决这个问题,只需将 expect(Schedule) 调用放在补丁调用之前,这也可以让您摆脱 allow(Schedule).to - 调用。

    干杯。

    【讨论】:

    • 感谢您的评论。我也试过了,这确实避免了上面的错误,但是它也不允许我测试对象的更改。例如,如果我想确认状态更改并为 expect(schedule.reload.status).to eq(2) 添加一个断言,则失败。有没有办法在这里维护它?
    • 您可能需要“.and_call_original”方法来实现这一点。当您断言方法调用时,方法不必在那里,这是那里的一种特性。这意味着没有你这么说它不会被调用。更新我的答案以表明这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多