Ruby on rails rspec中未实现的存根方法

Ruby on rails rspec中未实现的存根方法,ruby-on-rails,ruby,ruby-on-rails-4,rspec,Ruby On Rails,Ruby,Ruby On Rails 4,Rspec,我正在测试我的模块,并决定将其与匿名类进行对比测试: subject(:klass) { Class.new { include MyModule } } MyModule使用方法name内部klass。为了让我的规范发挥作用,我需要存根这个方法name(它尚未实现)。于是我写道: subject { klass.new } allow(subject).to receive(:name).and_return('SOreadytohelp') } 但它提出: RSpec::Mocks

我正在测试我的模块,并决定将其与匿名类进行对比测试:

  subject(:klass) { Class.new { include MyModule } }
MyModule
使用方法
name
内部
klass
。为了让我的规范发挥作用,我需要存根这个方法
name
(它尚未实现)。于是我写道:

subject { klass.new }
allow(subject).to receive(:name).and_return('SOreadytohelp') }
但它提出:

 RSpec::Mocks::MockExpectationError: #<#<Class:0x007feb67a17750>:0x007feb67c7adf8> does not implement: name
from spec-support-3.3.0/lib/rspec/support.rb:86:in `block in <module:Support>'
RSpec::Mocks::MockExpectationError:#未实现:name
来自spec-support-3.3.0/lib/rspec/support.rb:86:in'block-in'
如何在不定义此方法的情况下存根此方法

subject(:klass) do 
  Struct.new(:name) do
   include MyModule
  end
end

RSpec引发此异常,因为存根原始对象上不存在的方法是没有用的

模拟方法总是容易出错,因为模拟的行为可能与原始实现不同,因此即使原始实现返回错误(或甚至不存在),规范也可能成功。允许模拟不存在的方法是完全错误的

因此,我认为你不应该试图绕过这个例外。只需向类中添加一个
name
方法,如果在测试环境之外运行,该方法将引发一个明确的异常:

def self.name
  raise NoMethodError  # TODO: check specs...
end

我认为,如果您正在编写的测试集中在您的
MyModule
模块上,并且该模块依赖于它所混入的类中的实例方法,那么我认为应该在测试模块时使用的匿名类中模拟该方法。例如:

module MyModule
  def call_name
    # expected implementation of #name to be
    # in the class this module is mixed into
    name
  end
end

RSpec.describe MyModule do
  let(:my_module_able) do
    Class.new do
      include MyModule

      # We don't care what the return value of this method is;
      # we just need this anonymous class to respond to #name
      def name
        'Some Name that is not SOReadytohelp'
      end
    end.new
  end

  describe '#call_name' do
    let(:name) { 'SOReadytohelp' }

    before do
      allow(my_module_able).to receive(:name).and_return(name)
    end

    it 'returns the name' do
      expect(my_module_able.call_name).to eq(name)
    end
  end
end

我不知道这是否是答案,但你有一个打字错误<代码>主题{klass.new}。不应该是:
subject{klass.new}
(缺少一个“c”)。试试看,让我们知道
name
应该是一个实例方法,返回
'sorreadytohelp'
@Stefan:我同意,这也是个好主意。取决于关注点:强调规范和代码是同步的,或者需要修复…NotImplementedError的定义:
NotImplementedError在当前平台上未实现功能时引发。例如依赖于+fsync+或+fork+系统调用的方法,如果底层操作系统或Ruby运行时不支持它们,则可能引发此异常。
当在未定义方法的接收器上调用方法并且未能响应+method\u missing+时,应引发此异常。需要纠正