微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Rspec 中的存根/模拟 Recaptcha 控制器问题规格Rspec 结果

如何解决Rspec 中的存根/模拟 Recaptcha 控制器问题规格Rspec 结果

我有一个控制器问题想要测试。我想存根或模拟 verify_recaptch 方法。一种带有 event_name 和其他参数 (v3),另一种不带参数 (v2)。但是,我似乎也无法存根/模拟。

任何解决方案都会很棒。我尝试了其他帖子中提到的一些策略,但没有奏效。相关:mocking/stubbing a controller recaptcha method with rspec in rails

控制器问题

# frozen_string_literal: true

module FormCaptcha
  extend ActiveSupport::Concern

  def wrap_recaptcha(event_name,success_proc,failure_proc,minimum_score: 0.5,render_action: "new")
    success = verify_recaptcha(action: event_name,minimum_score: minimum_score,secret_key: '123')
    checkBox_success = verify_recaptcha unless success
    if success || checkBox_success
      success_proc.call
    else
      @show_checkBox_recaptcha = true unless success
      failure_proc.call
    end
  end

  private

  def show_checkBox_recaptcha
    @show_checkBox_recaptcha || params[:show_checkBox_recaptcha]
  end
end

规格

# frozen_string_literal: true

require "rails_helper"

RSpec.describe FormCaptcha do
  class FormCaptchaTest 
    include FormCaptcha
    
    def create
      success_proc = proc {
        'success'
      }

      failure_proc = proc {
        'failure'
      }

      wrap_recaptcha('test_action',failure_proc)
    end
  end

  describe "wrap_recaptcha" do
    before do
      @form_control = FormCaptchaTest.new
    end
    
    it "wrap_recaptcha should be included" do
      expect(@form_control).to respond_to(:wrap_recaptcha)
    end
    
    it "Verfy_recaptch false" do
      expect_any_instance_of(FormCaptchaTest).to receive(:verify_recaptcha).and_return(false)
      expect(create).to eql('failure')
    end
    
    it "Verfy_recaptch true" do
      expect_any_instance_of(FormCaptchaTest).to receive(:verify_recaptcha).and_return(true)
      expect(create).to eql('success')
    end
  end
end

Rspec 结果

FormCaptcha
  wrap_recaptcha
    wrap_recaptcha should be included
    Verfy_recaptch false (Failed - 1)
    Verfy_recaptch true (Failed - 2)

Failures:

  1) FormCaptcha wrap_recaptcha Verfy_recaptch false
     Failure/Error: expect(create).to eql('failure')
     
     ArgumentError:
       wrong number of arguments (given 0,expected 1+)
     # /Users/aa/.rvm/gems/ruby-2.7.1/gems/factory_bot-5.1.1/lib/factory_bot/strategy_Syntax_method_registrar.rb:19:in `block in define_singular_strategy_method'
     # ./spec/controllers/concerns/form_captcha_spec.rb:33:in `block (3 levels) in <top (required)>'

  2) FormCaptcha wrap_recaptcha Verfy_recaptch true
     Failure/Error: expect(create).to eql('success')
     
     ArgumentError:
       wrong number of arguments (given 0,expected 1+)
     # /Users/aa/.rvm/gems/ruby-2.7.1/gems/factory_bot-5.1.1/lib/factory_bot/strategy_Syntax_method_registrar.rb:19:in `block in define_singular_strategy_method'
     # ./spec/controllers/concerns/form_captcha_spec.rb:38:in `block (3 levels) in <top (required)>'

Finished in 0.22492 seconds (files took 3.46 seconds to load)
3 examples,2 failures

Failed examples:

rspec ./spec/controllers/concerns/form_captcha_spec.rb:31 # FormCaptcha wrap_recaptcha Verfy_recaptch false
rspec ./spec/controllers/concerns/form_captcha_spec.rb:36 # FormCaptcha wrap_recaptcha Verfy_recaptch true

解决方法

expect(create).to eql('success') 没有调用 FormCaptchaTest#create。在不提供对象的情况下,self.create 是导入的 FactoryBot#create

     ArgumentError:
       wrong number of arguments (given 0,expected 1+)
     # /Users/aa/.rvm/gems/ruby-2.7.1/gems/factory_bot-5.1.1/lib/factory_bot/strategy_syntax_method_registrar.rb:19:in `block in define_singular_strategy_method'
                                           ^^^^^^^^^^^^^^^^^

此外,您的测试实际上从未运行过 wrap_recaptcha。它不必为全班模拟。

  describe "wrap_recaptcha" do
    # Use `let` to make test objects on the fly instead of instance variables.
    let(:form_control) { FormCaptchaTest.new }

    # this test is redundant,if the method doesn't exist the other tests will fail
    it "wrap_recaptcha should be included" do
      expect(form_control).to respond_to(:wrap_recaptcha)
    end

    # Use contexts to set up your conditions separate from the tests.
    # It helps organize and describe the test,and makes the situation reusable.
    context 'when verify_recaptcha fails' do
      # This will be run before each example.
      before {
        # Use allow for mocks.
        allow(form_control).to receive(:verify_recaptcha).and_return(false)
      }

      # Run the method,check what it returned.
      it 'runs the failure proc' do
        expect(form_control.capture).to eq 'failure'
      end
    end
    
    context 'when verify_recaptcha succeeds' do
      before {
        allow(form_control).to receive(:verify_recaptcha).and_return(true)
      }

      it 'runs the failure proc' do
        expect(form_control.capture).to eq 'success'
      end
    end
  end

我建议进一步更改。奇怪的是 wrap_recaptcha 测试不运行 wrap_recaptcha,它们围绕包装器运行测试包装器。您可以改为利用 subject。这避免了必须建立一个大的测试类,随着测试的增长,它可能会开始干扰自身。

RSpec.describe FormCaptcha do
  class FormCaptchaTest 
    include FormCaptcha
  end

  let(:form_control) { FormCaptchaTest.new }

  describe "wrap_recaptcha" do
    # You can run this explicitly as `subject`.
    subject do
      form_control.wrap_recaptcha(
        'test_action',proc { 'success' },proc { 'failure' }
      )
    end

    context 'when verify_recaptcha fails' do
      before {
        allow(form_control).to receive(:verify_recaptcha).and_return(false)
      }

      it "should be 'failure'" do
        expect(subject).to eq 'failure'
      end
    end
    
    context 'when verify_recaptcha succeeds' do
      before {
        allow(form_control).to receive(:verify_recaptcha).and_return(true)
      }

      # Or use the "one-liner" syntax equivalent to the above.
      it { is_expected.to eq 'success' }
    end
  end
end

每个测试都定义了避免测试相互干扰所需的内容。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。