在rspec中存根未实现的方法

我正在测试我的模块,我决定测试它与匿名类:

subject(:klass) { Class.new { include MyModule } } 

MyModuleklass使用方法name 。 为了让我的规范工作,我需要存根这个方法name (未实现)。 所以我写道:

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

但它引起了:

  RSpec::Mocks::MockExpectationError: #<#:0x007feb67c7adf8> does not implement: name from spec-support-3.3.0/lib/rspec/support.rb:86:in `block in ' 

如何在不定义的情况下存根此方法?

RSpec引发了这个exception,因为对原始对象上不存在的方法进行存根是没有用的。

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

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

 def self.name raise NotImplementedError # TODO: check specs... end 
 subject(:klass) do Struct.new(:name) do include MyModule end end 

http://ruby-doc.org/core-2.2.0/Struct.html

我认为如果你正在编写的测试集中在你的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