如何在不使用 eval 方法的情况下使用参数化代码制作 RSpec 的共享示例以进行测试?

How to make shared example with RSpec with parametrized code to test without using eval method?

我在RSpec中有一个共享示例,它测试短信发送。在我的应用程序中,我几乎没有发送短信的方法,所以我想参数化我测试的代码,以便我可以将我的共享示例用于我的所有方法。我发现的唯一方法是使用 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

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

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

it_behaves_like "sending an sms",
  "post :create, params: reservation_attributes"

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

Failure/Error: post :create, params: reservation_attributes reservation_attributes is not available on an example group (e.g. a describe or context block). It is only available from within individual examples (e.g. it blocks) or from constructs that run in the scope of an example (e.g. before, let, etc).

实际上在你的例子中,action 和 params 可以作为参数传递到共享示例中:

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

并称为:

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

it_behaves_like "sending an sms", :create, reservation_attributes

或者你可以定义separate action for every block

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