How can I test that no attribute on a model has been modified using rspec?

六月ゝ 毕业季﹏ 提交于 2020-01-03 16:54:12

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!