Rspec - 覆盖 method_missing 和 respond_to_missing 后的参数错误
Rspec - Argument error after overwriting method_missing and respond_to_missing
我有一个控制器,我想为rspec编写
results_controller.rb
class Api::V1::ResultsController < Api::V1::ApplicationController
before_action :devices
include DataHelper
def show
results = get_dr_results
render json: { data: results }
end
private
def get_dr_results
program_ids = method_defined_in_crucible_helper
end
end
module DataHelper
include Cruciblehelper
def method_missing(method_name, *args, &block)
if condition
do_something
else
super.method_missing(method_name, *args, &block)
end
end
def respond_to_missing?
true
end
end
module CrucibleHelper
def method_defined_in_crucible_helper
end
end
现在在我的 rspec 中,我尝试模拟方法 method_defined_in_crucible_helper。
describe Api::V1::DrResultsController, type: :controller do
describe 'GET #show' do
before do
allow_any_instance_of(CrucibleHelper).to receive(:method_defined_in_crucible_helper) { [utility_program.id, utility_program2.id] }
end
context 'returns data' do
context 'returns expected events' do
it 'should return success response with expected events' do
get :show
expect(JSON.parse(response.body)).to eq(expected_response)
end
end
我得到
Failure/Error:
def respond_to_missing?
true
end
ArgumentError:
wrong number of arguments (given 2, expected 0)
# ./app/helpers/data_helper.rb:72:in `respond_to_missing?'
如果我注释掉respond_to_missing呢?方法,然后我的规格执行正常。有人可以帮我解决这个错误吗?
Ruby Delegator#respond_to_missing?
是负责返回缺少的方法是否能够被对象处理的方法,它有 2 个参数:missing method name
和选项 include_private
.
最佳做法是:always define respond_to_missing?
when overriding method_missing
。
但是我不喜欢你的申请方式,背后的原因是最小惊喜规则,看看:
class DataHelper
def method_missing(method_name, *args, &block)
if method_name.to_s.start_with?('delegate')
puts "a delegate method"
else
super
end
end
def respond_to_missing?(method_name, include_private = false)
true
end
end
d = DataHelper.new
d.respond_to?(:answer) # true
d.answer # `method_missing': undefined method `answer' ... SURPRISE
如您所见,d
响应他可以负责 answer
方法,但是当调用该方法时,会引发 method_missing
错误。
因此,您需要使 method_missing
和 respond_to_missing?
匹配在一起:
class DataHelper
def method_missing(method_name, *args, &block)
if can_handle?(method_name)
puts "a delegate method"
else
super
end
end
def respond_to_missing?(method_name, include_private = false)
return true if can_handle?(method_name)
super
end
private
def can_handle?(method_name)
method_name.to_s.start_with?('delegate')
end
end
d = D.new
d.respond_to?(:delegate_answer) # true
d.delegate_answer # delegate method
d.respond_to?(:answer) # false
d.answer # error
我有一个控制器,我想为rspec编写
results_controller.rb
class Api::V1::ResultsController < Api::V1::ApplicationController
before_action :devices
include DataHelper
def show
results = get_dr_results
render json: { data: results }
end
private
def get_dr_results
program_ids = method_defined_in_crucible_helper
end
end
module DataHelper
include Cruciblehelper
def method_missing(method_name, *args, &block)
if condition
do_something
else
super.method_missing(method_name, *args, &block)
end
end
def respond_to_missing?
true
end
end
module CrucibleHelper
def method_defined_in_crucible_helper
end
end
现在在我的 rspec 中,我尝试模拟方法 method_defined_in_crucible_helper。
describe Api::V1::DrResultsController, type: :controller do
describe 'GET #show' do
before do
allow_any_instance_of(CrucibleHelper).to receive(:method_defined_in_crucible_helper) { [utility_program.id, utility_program2.id] }
end
context 'returns data' do
context 'returns expected events' do
it 'should return success response with expected events' do
get :show
expect(JSON.parse(response.body)).to eq(expected_response)
end
end
我得到
Failure/Error:
def respond_to_missing?
true
end
ArgumentError:
wrong number of arguments (given 2, expected 0)
# ./app/helpers/data_helper.rb:72:in `respond_to_missing?'
如果我注释掉respond_to_missing呢?方法,然后我的规格执行正常。有人可以帮我解决这个错误吗?
Ruby Delegator#respond_to_missing?
是负责返回缺少的方法是否能够被对象处理的方法,它有 2 个参数:missing method name
和选项 include_private
.
最佳做法是:always define respond_to_missing?
when overriding method_missing
。
但是我不喜欢你的申请方式,背后的原因是最小惊喜规则,看看:
class DataHelper
def method_missing(method_name, *args, &block)
if method_name.to_s.start_with?('delegate')
puts "a delegate method"
else
super
end
end
def respond_to_missing?(method_name, include_private = false)
true
end
end
d = DataHelper.new
d.respond_to?(:answer) # true
d.answer # `method_missing': undefined method `answer' ... SURPRISE
如您所见,d
响应他可以负责 answer
方法,但是当调用该方法时,会引发 method_missing
错误。
因此,您需要使 method_missing
和 respond_to_missing?
匹配在一起:
class DataHelper
def method_missing(method_name, *args, &block)
if can_handle?(method_name)
puts "a delegate method"
else
super
end
end
def respond_to_missing?(method_name, include_private = false)
return true if can_handle?(method_name)
super
end
private
def can_handle?(method_name)
method_name.to_s.start_with?('delegate')
end
end
d = D.new
d.respond_to?(:delegate_answer) # true
d.delegate_answer # delegate method
d.respond_to?(:answer) # false
d.answer # error