Jeremy Thomas
Jeremy Thomas

Reputation: 6684

Rspec: Mock recaptcha verification

I am trying to create a request spec for a form submission and my recaptcha verification is causing the test to fail. I have a pretty simple test:

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

I run into an issue because in PotentialClients#create I make a call to verify_recaptcha? which returns false in the test instead of true:

# 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

How should I mock the call to verify_recapthca? so that my test passes? I've tried:

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

but both threw errors:

PotentialClient(...) does not implement: verify_recaptcha?

Upvotes: 2

Views: 908

Answers (1)

Jordan Running
Jordan Running

Reputation: 106037

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

This isn't working because—as the error message says—PotentialClient (the model) doesn't have a method called verify_recaptcha?. The method is defined in ApplicationController, which is extended by PotentialClientsController, and that's where you need to mock it.

My Rails is rusty, but it looks like in an rspec-rails controller spec the current instance of the controller is exposed by the controller method. In that case, what you want is this:

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

Upvotes: 1

Related Questions