Invalid Stub method in rspec

I am testing my module, and I decided to test it against an anonymous class:

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

MyModule uses the name method inside klass . For my specifications to work, I need to stub this name method (which is not implemented). Therefore, I wrote:

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

but he raises:

  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>' 

how to drown out this method without defining it?

+9
source share
3 answers

RSpec raises this exception because it is useless to stub a method that does not exist in the source object.

Re-mixing methods are always error-prone, because the simulation may not behave like the original implementation, and therefore the specifications can be successful even if the original implementation would return an error (or even not exist). Allowing to simulate non-existent methods is simply wrong.

Therefore, I would say that you should not try to get around this exception. Just add the name method to your class that throws an explicit exception when running outside the test environment:

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

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

+3
source

I think that if the test you are writing is focused on your MyModule module, and this module relies on the instance method in the class into which it is mixed, then I think that this method should be packaged into the anonymous class that you use when module testing. For instance:

 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 
+1
source

All Articles