Stubbing instance variables in RSpec 3.2

11,154

I think this is not a correct practice. Rspec should be testing the interface behaviour of classes, not the internal implementation.

As you are not using accessor, you can use #instance_variable_set & #instance_variable_get to manipulate and get the instance variable.

Getting and Setting are like follows:

@a.instance_variable_set(:@x, 5)
@a.instance_variable_get(:@x)
#=> 5

In your code:

@a.instance_variable_set(:@x, 5)
expect(@a.add(8)).to eq(13)
Share:
11,154
user2490003
Author by

user2490003

Updated on June 26, 2022

Comments

  • user2490003
    user2490003 almost 2 years

    I'm using RSpec 3.2 in Rails and wondering how I can stub instance variables if they are not publicly made accessible by a getter method (e.g. using attr_accessor or similar).

    Consider the simple example below -

    require 'rails_helper'
    
    class A
      def initialize
        @x = 3
      end
    
      def add(n)
        sum = @x + n
        puts "Sum is #{sum}"
        sum
      end
    end
    
    
    RSpec.describe A do
      before(:all) do
        @a = A.new
      end
    
      it 'computes the sum correctly' do
        # For this test I want to stub the value of @x and return 5
        allow(@a).to receive(:x) { 5 }
        # 5 + 8 should return 13
        expect(@a.add(8)).to eq(13)
      end
    end
    

    Trying to stub @x is not possible in this scenario as the class never never receives a message or method call for x. The RSpec output confirms this -

    Failures:
    
      1) A computes the sum correctly
         Failure/Error: allow(@a).to receive(:@x) { 5 }
           #<A:0x007fe6e66ab8d0 @x=3> does not implement: @x
         # ./spec/unit/test_spec.rb:25:in `block (2 levels) in <top (required)>'
    

    I could work around this by making the instance variable @x accessible (attr_accesssor :x) and replacing the call to @x with self.x, but that seems hacky and may not be possible in my more complex implementation.

    Is there a better way to stub this?

    Thanks!