问题
I want to check if no attributes on an ActiveRecord object have been modified. Currently I'm doing this:
prev_attr = obj.attributes
<- this will give me back a Hash with attr name and attr value
And then, later, I grab the attributes again and compare the 2 hashes. Is there another way?
回答1:
You should just be able to use equality matchers - does this not work for you?
a = { :test => "a" }
b = { :test => "b" }
$ a == b
=> false
b = { :test => "a" }
$ a == b
=> true
Or to use your example:
original_attributes = obj.attributes
# do something that should *not* manipulate obj
new_attributes = obj.attributes
new_attributes.should eql original_attributes
回答2:
There is another way indeed. You can do it like this :
it "should not change sth" do
expect {
# some action
}.to_not change{subject.attribute}
end
See https://www.relishapp.com/rspec/rspec-expectations/v/2-0/docs/matchers/expect-change.
回答3:
You can use ActiveRecord::Dirty. It gives you a changed?
method on your model which is truthy if any attribute of the model was actually changed and falsey if not. You also have _changed?
methods for each attribute, e.g. model.subject_changed?
which is truthy if that attribute was changed compared to when the object was read from the database.
To compare attribute values, you can use model.subject_was
which will be the original value the attribute had when the object was instantiated. Or you can use model.changes
which will return a hash with the attribute name as the key and a 2-element array containing the original value and the changed value for each changed attribute.
回答4:
Not a perfect solution, but as is mentioned here, I prefer it due to maintainability.
The attributes are cached, and since they're not changed directly you'll have to reload them if you want to check them all at once:
it 'does not change the subject attributes' do
expect {
# Action
}.to_not change { subject.reload.attributes }
end
Avoid reloading if you can, since you're forcing another request to the database.
来源:https://stackoverflow.com/questions/10478746/how-can-i-test-that-no-attribute-on-a-model-has-been-modified-using-rspec