How can I allow a superclass method to return something else?

120 Views Asked by At

Given two classes, Superclass and Subclass -

How can I use an allow on the Superclass to return something different?

#=> given `rspec` is in your $LOAD_PATH, this should be an SSCCE
require 'rspec'

class Superclass
  def superclass_method
    true
  end
end

class Subclass < Superclass
  def subclass_method
    superclass_method
  end
end

descriptor = RSpec.describe Subclass do
  describe '#subclass_method' do
    subject(:subclass) { described_class.new }

    let(:superclass) { spy('superclass') }

    before do
      stub_const('Superclass', superclass)
      allow(superclass).to receive(:superclass_method).and_return false
    end

    it 'should return false' do
      expect(subclass.subclass_method).to eq(false)
    end
  end
end

p descriptor.run

The output of p descriptor.run returns false for the above code (i.e., the test failed), while true is given when I change the expectation to expect(subclass.subclass_method).to eq(true).

I feel like I'm missing something simple here.

I've done some debugging and I see a few things:

subclass.subclass_method     #=> true
subclass.superclass_method   #=> true
superclass.superclass_method #=> false

I see that it's fine on the third line here, but I'm not sure how to return this when called from the Subclass

1

There are 1 best solutions below

0
ddavison On

I was able to accomplish this without using a double on the Superclass at all!

I changed the description block to:

describe '#subclass_method' do
  subject(:subclass) { described_class.new }

  before do
    allow(subclass).to receive(:superclass_method).and_return(false)
  end

  it 'should return false' do
    expect(subclass.subclass_method).to eq(false)
  end
end

Instead of using spies and stubbing the constant for the Superclass, I was able to mock the superclass method within the context of the Subclass. ‍♂️