Rspec: 模拟 recaptcha 验证

Rspec: Mock recaptcha verification

我正在尝试为表单提交创建请求规范,但我的 recaptcha 验证导致测试失败。我有一个非常简单的测试:

RSpec.describe "PotentialClients", type: :request do
  let(:pc_attributes) { ... }

  describe "POST /potential_clients" do

    it "should create record" do
      expect { post potential_clients_path, params: { potential_client: pc_attributes } }
        .to change(PotentialClient, :count).by(+1)
    end

  end
end

我 运行 遇到了一个问题,因为在 PotentialClients#create 中我调用了 verify_recaptcha?,在测试中 returns false 而不是 [=18] =]:

# potential_clients_controller.rb
def create
    @potential_client = PotentialClient.new(potential_client_params)
    page_success = verify_recaptcha?(params[:recaptcha_token], 'lead_creation_page')

    if page_success && @potential_client.save
        ...
    end
end

# application_controller.rb
def verify_recaptcha?(token, recaptcha_action)
  secret_key = ENV['CAPTCHA_SECRET_KEY']

  uri = URI.parse("https://www.google.com/recaptcha/api/siteverify?secret=#{secret_key}&response=#{token}")
  response = Net::HTTP.get_response(uri)
  json = JSON.parse(response.body)
  if json['success'] && json['score'] > RECAPTCHA_MINIMUM_SCORE && (json['action'] == "lead_creation_page" || json['action'] == "lead_creation_modal")
    return true
  elsif json['success'] == false && json["error-codes"].include?("timeout-or-duplicate")
    return true
  end

  return false
end

我应该如何模拟对 verify_recapthca? 的调用以便我的测试通过? 我试过:

allow(PotentialClient).to receive(:verify_recaptcha?).and_return(true)
# and 
allow_any_instance_of(PotentialClient).to receive(:verify_recaptcha?).and_return(true)

但都抛出错误:

PotentialClient(...) does not implement: verify_recaptcha?
allow(PotentialClient).to receive(:verify_recaptcha?).and_return(true)

这是行不通的,因为正如错误消息所说,PotentialClient(模型)没有名为 verify_recaptcha? 的方法。该方法定义在 ApplicationController 中,它由 PotentialClientsController 扩展,这就是您需要模拟它的地方。

我的 Rails 生锈了,但它看起来像在 rspec-rails 控制器规范中,控制器的当前实例由 controller 方法公开。在那种情况下,你想要的是:

allow_any_instance_of(ApplicationController).to receive(:verify_recaptcha?).and_return(true)