ruby-on-rails - RSpec:如何进行一个 shared_example 测试来测试许多不同的控制器 PATCH 请求,这些请求都更新不同的属性?
问题描述
我有各种控制器,并且我对每个控制器都进行了测试,以测试它们的更新操作。测试具有完全相同的结构:它测试补丁请求是否会更新和更改对象。这些测试之间的唯一区别是测试检查哪些属性以查看其更改断言。这些属性是控制器独有的。
class CarsController
def update
# update attribute
...
end
end
和
class DogsController
def update
# update attribute
...
end
end
我的测试(更多的两个):
CarsSpec
describe "PATCH" do
it "should update the car" do
expect do
patch :update, id: object.id, data: {make: "honda"}
end.to change {object.reload.make}
end
end
DogSpec
describe "PATCH" do
it "should update the dog" do
expect do
patch :update, id: object.id, data: {breed: "husky"}
end.to change {object.reload.breed}
end
end
正如你所看到的,它们自然是完全相同的测试结构,为了干燥,我想将它们提取到一个 shared_example 中以便干燥。我们的想法是拥有更多这些控制器,但只是实际测试,并且这些控制器只是通过哪个字段进行更新。它会涉及到类似的东西
shared_example "update" do
it "updates the object" do
expect do
patch :update, id.object.id, data: { customField: "new value" }
end.to change { object.reload.customField }
end
end
在这种情况下,customField 可以是品种或制造,并且测试会知道更新这些字段,因此它是通用的并且可以应用于许多这些控制器。我怎样才能做到这一点或类似的东西?
解决方案
shared_example
的块接受参数:
shared_example "update" do |custom_field|
it "updates the object (field: #{custom_field})" do
expect do
patch :update, id.object.id, data: { custom_field => "new value" }
end.to change { object.reload.public_send(custom_field) }
end
end
并将其称为
include_examples 'update', :make
include_examples 'update', :breed