为什么这个规范中的第二个'delete:destroy'没有运行?

时间:2016-11-29 12:15:24

标签: ruby-on-rails rspec

我的规格会产生意想不到的结果。我无法追查原因。谁能帮助我指出正确的方向?

let(:object1) { create :object }
let(:object2) { create :object }
let(:user)    { create :user }
describe "DELETE #destroy" do
  before :each do
    Rails.logger.info "Object 1 ID: #{object1.id}"
    Rails.logger.info "Object 2 ID: #{object4.id}"
    user.roles.push Role.where(name: 'FullAccess').first
    sign_in user
    delete :destroy, {:id => object1.to_param}
  end
  it {
     expect {
       delete :destroy, {:id => object2.to_param}
     }.to change(Object, :count).by(-1)
  }
end 

结果

Failure/Error:
  expect {
    delete :destroy, {:id => object2.to_param}
  }.to change(Object, :count).by(-1)
expected #count to have changed by -1, but was changed by 0

但如果我在之前的区块中注释delete,则测试通过。

before :each do
  sign_in user
  # delete :destroy, {:id => office1.to_param}
end

为什么不删除第二个对象?

修改

正在测试的方法是

def ObjectController < ApplicationController
  load_and_authorize_resource
  def destroy
    Rails.logger.info "DELETE OBJECT ID: #{@object.id}" 
    @object.destroy
    respond_to do |format|
      format.html { redirect_to objects_url, notice: t('.notice') }
      format.json { head :no_content }
    end
  end
end

编辑2

在上面的示例中添加了日志记录代码。日志输出现在包括

Object 1 ID: 1
Object 2 ID: 2
DELETE OBJECT ID: 1 
DELETE OBJECT ID: 1 

1 个答案:

答案 0 :(得分:3)

1。懒惰评估

这是因为您的object2已在expect块中创建并立即销毁。 let is lazy, let! is immediately evaluated

将您的let更改为let!,它应该有效:

let!(:object1) { create :object }
let!(:object2) { create :object }
describe "DELETE #destroy" do
  before :each do
    sign_in user
    delete :destroy, {:id => object1.to_param}
  end
  it {
     expect {
       delete :destroy, {:id => object2.to_param}
     }.to change(Object, :count).by(-1)
  }
end

2。记忆对象

至于问题的其他部分,您看到规范失败的原因是因为前一个块中的控制器与测试中的实例相同。仅在尚未设置对象时才设置该对象,因此在第二次调用delete方法时不会重置该对象(使用不同的参数)。这样的事情正在发生:

@object ||= Object.find(...)

删除对before块中测试中的控制器操作的删除调用应解决此问题。