Ruby on rails RSpec 3.2中的存根实例变量

Ruby on rails RSpec 3.2中的存根实例变量,ruby-on-rails,ruby,rspec,Ruby On Rails,Ruby,Rspec,我正在Rails中使用RSpec3.2,并想知道如果getter方法(例如使用attr\u访问器或类似方法)未公开访问实例变量,我如何能够存根它们 考虑下面的简单示例- 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 b

我正在Rails中使用RSpec3.2,并想知道如果getter方法(例如使用
attr\u访问器
或类似方法)未公开访问实例变量,我如何能够存根它们

考虑下面的简单示例-

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
在这种情况下,尝试存根
@x
是不可能的,因为类从未收到
x
的消息或方法调用。RSpec输出证实了这一点-

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)>'
故障:
1) A正确计算总数
失败/错误:允许(@a).接收(:@x){5}
#未实现:@x
#./spec/unit/test_spec.rb:25:in‘分块(2级)in’
我可以通过使实例变量
@x
可访问(
attr\u accessor:x
)并将对
@x
的调用替换为
self.x
,来解决这个问题,但这似乎有点老套,在我更复杂的实现中可能无法实现

有没有更好的方法来存根这个


谢谢

我认为这不是一种正确的做法。Rspec应该测试类的接口行为,而不是内部实现

由于不使用accessor,因此可以使用&来操作和获取实例变量

获取和设置如下所示:

@a.instance_variable_set(:@x, 5)
@a.instance_variable_get(:@x)
#=> 5
在代码中:

@a.instance_variable_set(:@x, 5)
expect(@a.add(8)).to eq(13)