Ruby Rspec:测试实例变量而不向源添加访问器


78

我正在尝试测试以下方法:

def unprocess_move(board, move)
  if move[0].instance_of?(Array)
    multi_move = @multi_move.pop(2).reverse
    multi_move.each do |single_move|
      unapply_move(board, single_move)
    end
  else
    board = unapply_move(board, move)
  end
  board
end

我想在这里设置@multi_move的状态,但是我不想添加访问器仅用于测试。没有访问者,有没有办法做到这一点?谢谢。

Answers:


130

您可以使用Object#instance_variable_getmethod来获取对象的任何实例变量的值,如下所示:

class Foo 
  def initialize
    @foo = 5 # no accessor for that variable
  end 
end

foo = Foo.new
puts foo.instance_variable_get(:@foo)
#=> 5

并且Object#instance_variable_set可以用来设置实例变量的值:

foo.instance_variable_set(:@foo, 12) 
puts foo.instance_variable_get(:@foo)
#=> 12

但是我需要在测试中预先设置它。在测试之前没有任何值。
steve_gallagher 2012年

1
@steve_gallagher,看看文档。还有instance_variable_set旁边的instance_variable_get(例如添加并链接到文档的答案)。
KL-7

1
有趣。我不知道您可以直接进入并设置并获取任何这样的实例变量。但是,我已经看过很多RSpec测试,而且从未见过这些方法被调用。似乎是一种非标准的方式来处理我认为很典型的情况。不过,我没有抱怨,谢谢您的回答。
steve_gallagher 2012年

17
@steve_gallagher,我认为您之前从未见过的原因是,在大多数情况下,您不应该测试对象的私有状态。如果要测试某个对象的行为和逻辑,则应该测试它的作用,而不是它的作用。如果您不提供对某些实例变量的公共访问权限(例如,在您的案例中未为其定义getter),则只要对象按其应有的方式运行,就不需要对象外部的任何人关心其状态。在您的情况下,最好测试结果,而不要设置某些实例变量。
KL-7

2
非常感谢您的解释,现在以不同的角度来看它,我不知道为什么以前没有注意到,显然我需要对其进行重构,以便不需要设置实例变量来证明方法有效。再次感谢。
steve_gallagher 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.