【问题标题】:Stubbing instance variables in RSpec 3.2RSpec 3.2 中的存根实例变量
【发布时间】:2015-03-30 03:26:19
【问题描述】:

我在 Rails 中使用 RSpec 3.2,想知道如果实例变量不能通过 getter 方法公开访问(例如使用 attr_accessor 或类似方法),我如何存根实例变量。

考虑下面的简单示例 -

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

我可以通过使实例变量 @x 可访问 (attr_accesssor :x) 并将对 @x 的调用替换为 self.x 来解决此问题,但这似乎很棘手,在我更复杂的实现中可能无法实现。

有没有更好的方法来存根?

谢谢!

【问题讨论】:

    标签: ruby-on-rails ruby rspec


    【解决方案1】:

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

    由于你没有使用访问器,你可以使用#instance_variable_set & #instance_variable_get 来操作和获取实例变量。

    获取和设置如下:

    @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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-08
      相关资源
      最近更新 更多