我的规格会产生意想不到的结果。我无法追查原因。谁能帮助我指出正确的方向?
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
在上面的示例中添加了日志记录代码。日志输出现在包括
Object 1 ID: 1
Object 2 ID: 2
DELETE OBJECT ID: 1
DELETE OBJECT ID: 1
答案 0 :(得分:3)
这是因为您的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
至于问题的其他部分,您看到规范失败的原因是因为前一个块中的控制器与测试中的实例相同。仅在尚未设置对象时才设置该对象,因此在第二次调用delete方法时不会重置该对象(使用不同的参数)。这样的事情正在发生:
@object ||= Object.find(...)
删除对before块中测试中的控制器操作的删除调用应解决此问题。