How to test dependent: :destroy with RSpec?
13,468
Solution 1
It is the right matcher, but you're not using it the correct way:
- expect needs to receive a block containing the action to perform (in your case deleting the user)
- change needs to receive a block that produces the numerical value that is expected to change (it can also receive an object and a symbol indicating that rspec should call the named method)
The correct way is
expect { user.destroy }.to change { Project.count }
This just asserts that the numerical value changes, but does not specify by how much. To do that, chain a call to by
:
expect { user.destroy }.to change { Project.count }.by(-1)
Solution 2
You can also use shoulda matchers:
it { expect(user).to have_many(:projects).dependent(:destroy) }
https://github.com/thoughtbot/shoulda-matchers
Solution 3
This should work:
expect { user.destroy }.to change { Project.count }.by(-1)
Solution 4
You should test for the removal of the actual project.
expect(Project.all).not_to include project
Author by
Xeen
Updated on June 18, 2022Comments
-
Xeen almost 2 years
I'd like to test my
User
models associationhas_many :projects, dependent: :destroy
and have gone this far for now:it "destroys dependent projects" do user = FactoryGirl.build(:user) project = FactoryGirl.build(:project) user.projects << project user.destroy expect(Project.count).to change(-1) end
but this gives out an error:
Failure/Error: expect(Project.count).to change(-1) ArgumentError: `change` requires either an object and message (`change(obj, :msg)`) or a block (`change { }`). You passed an object but no message.
so I presume that
change
isn't the right matcher, is it? Can you please tell me how I could write this test without getting that error?