2012-01-27 29 views
41

给定一个包含几个实例变量和一些方法的类。一些实例变量可通过attr_readerattr_accessor访问。因此其他人是私人的。
一些私有实例变量在其中一个实例方法中被设置并在另一个方法中读取/使用。如何设置方法测试中使用的私有实例变量?

为了测试我正在使用RSpec。由于我对Ruby还是个新手,并且想要把所有的东西都搞定,所以我将测试定义得相当细致。因此,对于每个实例方法,我都有一个describe块,它们本身被划分为contextit的子集。一般环境前提条件定义为before

但是,当测试其中一个方法,即利用但不设置其中一个私有变量时,我需要调用另一个方法,即设置此变量。这看起来相当超重,对我来说不是模块化的。

有没有办法强制一个私人实例变量到某个值。类似于“取出”的私有实例变量的值,其值为Object::instance_eval(:var)

回答

78

正如你在你的问题回答设置实例变量的最简单的方法是用instance_eval方法:

obj.instance_eval('@a = 1') 

另一种方法是使用instance_variable_set:

obj.instance_variable_set(:@a, 1) 

但我不会推荐这样做我n你的规格。规格都是关于对象的测试行为,通过使用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) 
+0

还没有想过存根访问器呢。可能会使我的很多测试数据(一些文本文件,应该由我的程序检测和解析)过时。看起来很不错。谢谢:) – 2012-01-27 19:18:35

+0

只是为了澄清,在你的答案中,你是否声称'instance_eval'打破了类封装或者'instance_variable_set'呢? – Seanny123 2013-12-16 08:28:41

+0

@ Seanny123'instance_eval'和'instance_variable_set'都修改了实例私有的内部状态,不应该在对象之外进行修改。 – 2013-12-16 10:25:59

7

使用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 
+0

感谢的为。我知道这很容易。 :) – 2012-01-27 19:03:23

相关问题