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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9038483/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 04:43:09  来源:igfitidea点击:

How to set private instance variable used within a method test?

rubytestingrspecaccess-specifier

提问by Torbj?rn

Given a class with a couple of instance variables and some methods. Some instance variables are set accessible via attr_readerand attr_accessor. Thus the others are private.
Some of the private instance variables get set within one of the instance methods and read/utilized within another method.

给定一个带有几个实例变量和一些方法的类。一些实例变量设置为可通过attr_reader和访问attr_accessor。因此其他人是私人的。
一些私有实例变量在一个实例方法中设置并在另一个方法中读取/使用。

For testing I'm using RSpec. As I'm still new to Ruby and want to get all things right, I defined my tests being rather fine-grained. Thus I've got one describeblock for each instance method, which themselves are partitioned into a subset of contexts and its. General environmental preconditions are defined with before.

为了测试,我使用 RSpec。由于我还是 Ruby 的新手并且想要把所有事情都做对,所以我将我的测试定义为相当细粒度的。因此describe,每个实例方法都有一个块,它们本身被划分为contexts 和its的子集。一般环境先决条件定义为before

However, when testing one of the methods, which is utilizing but not setting one of the private variables, I need to call the other method, which is setting this variable. This seems rather overweight and not modular for me.

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

Is there a way of forcing a private instance variable to a certain value. Similar to "ripping out" the value of a private instance variable with Object::instance_eval(:var).

有没有办法将私有实例变量强制为某个值。类似于“撕掉”私有实例变量的值Object::instance_eval(:var)

回答by Aliaksei Kliuchnikau

As you answered in your question the easiest way to set instance variable is with instance_evalmethod:

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

obj.instance_eval('@a = 1')

Another way is to use instance_variable_set:

另一种方法是使用 instance_variable_set:

obj.instance_variable_set(:@a, 1)

But I would not recommend to do this in your specs. Specs are all about testing behavior of an object and testing behaviour by breaking class encapsulation with instance_evalwill make your tests more fragile and implementation dependent.

但我不建议在您的规范中执行此操作。规范都是关于测试对象的行为,并且通过破坏类封装来测试行为instance_eval将使您的测试更加脆弱并依赖于实现。

Alternative approach to object state isolation is to stub accessor methods:

对象状态隔离的另一种方法是存根访问器方法:

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)

回答by robbrit

Use instance_variable_set:

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

回答by Chris

I just solved it by creating a child and adding an accessor:

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

class HasSecrets
  @muahaha
end

class TestMe < HasSecrets
  attr_accessor(:muahaha)
end

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