如何设置方法测试中使用的私有实例变量?

时间:2012-01-27 18:50:36

标签: ruby testing rspec access-specifier

给定一个包含几个实例变量和一些方法的类。某些实例变量可通过attr_readerattr_accessor设置。因此其他人都是私人的 某些私有实例变量在其中一个实例方法中设置,并在另一个方法中读取/使用。

测试我正在使用RSpec。由于我还是Ruby的新手,并且想要把所有事情都搞定,我将我的测试定义得相当精细。因此,我为每个实例方法都有一个describe块,它们本身被划分为context s和it s的子集。一般环境先决条件由before定义。

但是,当测试其中一个方法,即使用但未设置其中一个私有变量时,我需要调用另一个方法,即设置此变量。这对我来说似乎相当超重而且不模块化。

是否有一种方法可以将私有实例变量强制转换为某个值。与“剥离”类似,私有实例变量的值为Object::instance_eval(:var)

3 个答案:

答案 0 :(得分:84)

在您的问题中回答,设置实例变量的最简单方法是使用instance_eval方法:

obj.instance_eval('@a = 1')

另一种方法是使用instance_variable_set:

obj.instance_variable_set(:@a, 1)

但我不建议在你的规格中这样做。规范是关于测试对象行为的,并且通过使用instance_eval破坏类封装来测试行为将使您的测试更加脆弱且依赖于实现。

对象状态隔离的替代方法是存根访问器方法:

class UnderTest
  attr_accessor :a

  def test_this
    do_something if a == 1
  end
end

#in your test
under_test = UnderTest.new
under_test.stub(:a).and_return(1)

答案 1 :(得分:8)

使用instance_variable_set

class SomeClass
  attr_reader :hello
  def initialize
    @hello = 5
  end
  # ...
end

a = SomeClass.new
a.hello    # => 5

a.instance_variable_set("@hello", 7)
a.hello    # => 7

答案 2 :(得分:0)

我只是通过创建一个孩子并添加一个访问器来解决它:

class HasSecrets
  @muahaha
end

class TestMe < HasSecrets
  attr_accessor(:muahaha)
end

def test_stuff
  pwned = TestMe.new()
  pwned.muahaha = 'calc.exe'
end