I am successfully testing whether certain properties of an ActiveRecord model are updated. I also want to test that ONLY those properties have changed. I was hoping I could hook into the model's .changes
or .previous_changes
methods to verify the properties I expect to change are the only ones being changed.
UPDATE
Looking for something equivalent to the following (which doesn't work):
it "only changes specific properties" do
model.do_change
expect(model.changed - ["name", "age", "address"]).to eq([])
end
Try something like this
expect { model.method_that_changes_attributes }
.to change(model, :attribute_one).from(nil).to(1)
.and change(model, :attribute_two)
If the changes are not attributes, but relations you might need to reload the model:
# Assuming that model has_one :foo
expect { model.method_that_changes_relation }
.to change { model.reload.foo.id }.from(1).to(5)
EDIT:
After some clarification from the OP comment:
You can do this then
# Assuming, that :foo and :bar can be changed, and rest can not
(described_class.attribute_names - %w[foo bar]).each |attribute|
specify "does not change #{attribute}" do
expect { model.method_that_changes_attributes }
.not_to change(model, attribute.to_sym)
end
end
end
This is essentially what you need.
This solution has one issue though: it will call method_that_changes_attributes
for each attribute, and this can be inefficient. If that's the case - you may want to make your own matcher that accepts an array of methods. Start here