Reputation: 473
I have created a simple Rspec test to verfiy if a model created has been deleted. However, the test fails because the model still exists. Can anyone provide any assistance on how to determine if the record was actually deleted?
RSpec.describe Person, type: :model do
let(:person) {
Person.create(
name: "Adam",
serial_number: "1"
)
}
it "destroys associated relationships when person destroyed" do
person.destroy
expect(person).to be_empty()
end
end
Upvotes: 25
Views: 11853
Reputation: 38418
You could test the behaviour like so:
expect do
person.destroy
end.to change(person, :persisted?).to false
If you test the behaviour you get two expectations for the price of one! ie: you can assert the before and after in one spec.
Also, the reload will raise an error, you could test that (I had to do this for some associations).
expect do
person.destroy
person.reload
end.to raise_error ActiveRecord::RecordNotFound
Upvotes: 1
Reputation: 106852
You have two choices. You can test that:
A record was removed from the database
it "removes a record from the database" do
expect { person.destroy }.to change { Person.count }.by(-1)
end
But that doesn't tell you which record was removed.
Or that the exact record does not exist in the database anymore
it "removes the record from the database" do
person.destroy
expect { person.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
or
it "removes the record from the database" do
person.destroy
expect(Person.exists?(person.id)).to be false
end
But that does not make sure that the record existed before.
A combination of both could be:
it "removes a record from the database" do
expect { person.destroy }.to change { Person.count }.by(-1)
expect { person.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
Upvotes: 42
Reputation: 161
I think the following is a nice way to test a specific record has been removed with one expectation, while ensuring your testing the result of the action and not just the state of your test subject.
it "removes the record from the database" do
expect { person.destroy }.to change { Person.exists?(person.id) }.to(false)
end
Upvotes: 8
Reputation: 3191
When you delete a record from a database, an object still persists in memory. That's why expect(person).to be_empty()
fails.
RSpec has the change
matcher. ActiveRecord has the persisted?
method. It returns false if a record is not persisted in a database.
it "destroys associated relationships when rtu destroyed" do
expect { person.destroy }.to change(Person, :count).by(-1)
expect(person.persisted?).to be_falsey
end
destroy
is a method of a framework. As far as I know, you don't need to test its methods.
Upvotes: 5