如何使用 RSpec 制作共享示例并使用参数化代码进行测试而不使用 eval 方法?

Kar*_*lak 4 rspec ruby-on-rails dry

我在 RSpec 中有一个共享示例,它测试 SMS 发送。在我的应用程序中,我有几个发送短信的方法,所以我想参数化我测试的代码,以便我可以将我的共享示例用于我的所有方法。我发现做到这一点的唯一方法是使用eval函数:

RSpec.shared_examples "sending an sms" do |action_code|
  it "sends an sms" do
    eval(action_code)
    expect(WebMock).to have_requested(**my_request**).with(**my_body**)
  end
end
Run Code Online (Sandbox Code Playgroud)

所以我可以这样使用这个例子:

it_behaves_like "sending an sms",
  "post :accept, params: { id: reservation.id }"

it_behaves_like "sending an sms",
  "post :create, params: reservation_attributes"
Run Code Online (Sandbox Code Playgroud)

在不使用函数的情况下如何实现这一目标eval?我尝试将模式与yield命令一起使用,但由于范围的原因它不起作用:

失败/错误:post:create,params:reservation_attributes 在示例组(例如 a或块)reservation_attributes上不可用。它只能从单个示例(例如块)中或在示例范围内运行的构造(例如,, 等)中获得。describecontextitbeforelet

Igo*_*dov 5

实际上,在您的情况下,操作和参数可以作为参数传递到共享示例中:

RSpec.shared_examples "sending an sms" do |action, params|
  it "sends an sms" do
    post action, params: params
    expect(WebMock).to have_requested(**my_request**).with(**my_body**)
  end
end
Run Code Online (Sandbox Code Playgroud)

并称为:

it_behaves_like "sending an sms", :accept, { id: reservation.id }

it_behaves_like "sending an sms", :create, reservation_attributes
Run Code Online (Sandbox Code Playgroud)

或者您可以为每个块定义单独的操作

RSpec.shared_examples "sending an sms" do
  it "sends an sms" do
    action
    expect(WebMock).to have_requested(**my_request**).with(**my_body**)
  end
end

it_behaves_like "sending an sms" do
  let(:action) { post :accept, params: { id: reservation.id } }
end

it_behaves_like "sending an sms" do
  let(:action) { post :create, params: reservation_attributes }
end
Run Code Online (Sandbox Code Playgroud)