如何解决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 举报,一经查实,本站将立刻删除。