如何测试使用rspec修改模型上的属性?
我想检查ActiveRecord对象上是否没有修改任何属性。 目前我这样做:
prev_attr = obj.attributes
< – 这将给我一个带有attr名称和attr值的Hash
然后,稍后,我再次获取属性并比较两个哈希值。 还有另一种方式吗?
你应该能够使用平等匹配器 – 这不适合你吗?
a = { :test => "a" } b = { :test => "b" } $ a == b => false b = { :test => "a" } $ a == b => true
或者使用你的例子:
original_attributes = obj.attributes # do something that should *not* manipulate obj new_attributes = obj.attributes new_attributes.should eql original_attributes
确实有另一种方式。 你可以这样做:
it "should not change sth" do expect { # some action }.to_not change{subject.attribute} end
请参阅https://www.relishapp.com/rspec/rspec-expectations/v/2-0/docs/matchers/expect-change 。
您可以使用ActiveRecord :: Dirty 。 它给你一个changed?
如果模型的任何属性实际更改,则模型上的方法是真实的,否则就是假的。 你也有_changed?
每个属性的方法,例如model.subject_changed?
如果与从数据库中读取对象相比,该属性发生了变化,这是真实的。
要比较属性值,可以使用model.subject_was
,它将是实例化对象时属性的原始值。 或者您可以使用model.changes
,它将返回一个带有属性名称作为键的哈希值,以及一个包含原始值和每个已更改属性的更改值的2元素数组。
不是一个完美的解决方案,但正如这里提到的,由于可维护性,我更喜欢它。
属性是缓存的,因为它们不会直接更改,所以如果要一次检查所有属性,则必须重新加载它们:
it 'does not change the subject attributes' do expect { # Action }.to_not change { subject.reload.attributes } end
如果可以,请避免重新加载,因为您正在强制向数据库发出另一个请求。