Reputation: 12653
I have a spec that is giving unexpected results. I've not been able to track down the cause. Can anyone help point me in the right direction?
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
Results in
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
But if I comment out delete
in the before block, the test passes.
before :each do
sign_in user
# delete :destroy, {:id => office1.to_param}
end
Why would the second object not be deleted?
The method being tested is
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
Added logging codes to the examples above. The log output now includes
Object 1 ID: 1
Object 2 ID: 2
DELETE OBJECT ID: 1
DELETE OBJECT ID: 1
Upvotes: 0
Views: 119
Reputation: 43996
This is because your object2
is created and immediately destroyed within the expect block. let
is lazy, let!
is immediately evaluated
Change your let
to let!
, and it should work:
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
As for the other part of the problem, the reason you're seeing the spec fail is because the controller in the before block is the same instance as in the test. The object is being set only if it's not already set, so it won't get reset on your second call to the delete method (with different params). Something like this is happening:
@object ||= Object.find(...)
Removing the delete call to the controller action under test in the before block should fix this.
Upvotes: 3