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

发布于 2024-12-29 12:37:28 字数 506 浏览 0 评论 0原文

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

为了进行测试,我使用 RSpec。由于我对 Ruby 还很陌生,并且希望一切都正确,因此我将测试定义得相当细粒度。因此,我为每个实例方法都有一个 describe 块,这些块本身被划分为 contextit 的子集。一般环境先决条件是用 before 定义的。

但是,当测试其中一种方法时,该方法正在利用但未设置其中一个私有变量,我需要调用另一种方法,即设置该变量。这对我来说似乎相当过重并且不模块化。

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

Given a class with a couple of instance variables and some methods. Some instance variables are set accessible via attr_reader and 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.

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 describe block for each instance method, which themselves are partitioned into a subset of contexts and its. General environmental preconditions are defined with 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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

只想待在家 2025-01-05 12:37:28

正如您在问题中回答的那样,设置实例变量的最简单方法是使用 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)

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

obj.instance_eval('@a = 1')

Another way is to use 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_eval will make your tests more fragile and implementation dependent.

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)
习ぎ惯性依靠 2025-01-05 12:37:28

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

Use 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
坏尐絯℡ 2025-01-05 12:37:28

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

class HasSecrets
  @muahaha
end

class TestMe < HasSecrets
  attr_accessor(:muahaha)
end

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文