【问题标题】:Rspec - Argument error after overwriting method_missing and respond_to_missingRspec - 覆盖 method_missing 和 respond_to_missing 后的参数错误
【发布时间】:2021-07-02 14:16:03
【问题描述】:

我有一个控制器,我想为其编写 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?方法,然后我的规格执行正常。有人可以帮我解决这个错误吗?

【问题讨论】:

  • def respond_to_missing?(method_name, include_private = false)
  • 嗨@LamPhan,请添加您的评论作为详细答案,因为这对我有用。

标签: ruby-on-rails rspec method-missing


【解决方案1】:

Ruby Delegator#respond_to_missing? 是负责返回缺失的方法是否能够被对象处理的方法,它有两个参数: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

【讨论】:

    猜你喜欢
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多