RSpec 测试仅期望 ActiveRecord 模型的某些属性发生变化
RSpec test to expect only certain properties of an ActiveRecord model to change
我正在成功测试 ActiveRecord 模型的某些属性是否已更新。我还想测试只有那些属性发生了变化。我希望我可以连接到模型的 .changes
或 .previous_changes
方法来验证我期望更改的属性是唯一被更改的属性。
更新
正在寻找与以下内容等同的内容(无效):
it "only changes specific properties" do
model.do_change
expect(model.changed - ["name", "age", "address"]).to eq([])
end
尝试这样的事情
expect { model.method_that_changes_attributes }
.to change(model, :attribute_one).from(nil).to(1)
.and change(model, :attribute_two)
如果更改的不是属性,而是关系,您可能需要重新加载模型:
# Assuming that model has_one :foo
expect { model.method_that_changes_relation }
.to change { model.reload.foo.id }.from(1).to(5)
编辑:
经过 OP 评论的一些澄清:
那你可以这样做
# 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
这基本上就是您所需要的。
这个解决方案有一个问题:它会为每个属性调用 method_that_changes_attributes
,这可能是低效的。如果是这种情况 - 您可能想要制作自己的匹配器来接受一系列方法。开始 here
也许这可以帮助:
model.do_change
expect(model.saved_changes.keys).to contain_exactly 'name', 'age', 'address'
这应该也适用于 .previous_changes
。
如果更改没有保存,那么 .changed
应该可以。
归根结底,这实际上取决于 do_change
上的情况
我正在成功测试 ActiveRecord 模型的某些属性是否已更新。我还想测试只有那些属性发生了变化。我希望我可以连接到模型的 .changes
或 .previous_changes
方法来验证我期望更改的属性是唯一被更改的属性。
更新
正在寻找与以下内容等同的内容(无效):
it "only changes specific properties" do
model.do_change
expect(model.changed - ["name", "age", "address"]).to eq([])
end
尝试这样的事情
expect { model.method_that_changes_attributes }
.to change(model, :attribute_one).from(nil).to(1)
.and change(model, :attribute_two)
如果更改的不是属性,而是关系,您可能需要重新加载模型:
# Assuming that model has_one :foo
expect { model.method_that_changes_relation }
.to change { model.reload.foo.id }.from(1).to(5)
编辑:
经过 OP 评论的一些澄清:
那你可以这样做
# 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
这基本上就是您所需要的。
这个解决方案有一个问题:它会为每个属性调用 method_that_changes_attributes
,这可能是低效的。如果是这种情况 - 您可能想要制作自己的匹配器来接受一系列方法。开始 here
也许这可以帮助:
model.do_change
expect(model.saved_changes.keys).to contain_exactly 'name', 'age', 'address'
这应该也适用于 .previous_changes
。
如果更改没有保存,那么 .changed
应该可以。
归根结底,这实际上取决于 do_change