【问题标题】:How to stop RSpec anonymous class leaking?如何阻止 RSpec 匿名类泄漏?
【发布时间】:2019-11-13 23:11:36
【问题描述】:

所以我正在尝试测试一个抽象类。根据我阅读的内容,给一个名为Foo的类,我可以在RSpec中做以下事情并且它不会泄漏到其他测试中。

let(:test) do
  Class.new(Foo) do
    # Do things here
  end
end

但是,当我在另一个位置执行Foo.subclasses(取决于规范执行顺序)时,我发现它仍然会泄漏。

我还尝试以正常方式定义类并在后块中将其删除,例如

let(:test) do
  class Test < Foo; end
  Test
end
...

after do
  Object.send(:remove_const, :Test)
end

但这似乎也不起作用。 Foo.subclasses 似乎仍然包含匿名类。

【问题讨论】:

  • 不确定是否可以取消声明匿名类。这些垃圾应该最终被收集起来,但可能不会像你希望的那样快。请记住,删除变量或常量不会自动删除关联的对象。这些可能由于其他原因而持续存在,例如它们是否作为子类列表中的参考而保留。

标签: ruby-on-rails ruby rspec rspec-rails activesupport


【解决方案1】:

我对 subclasses 的工作原理进行了一些调查,这就是我发现的(虽然不是你问题的真正答案)

subclasses 内部调用descendants(它们都来自ActiveSupport)调用ObjectSpace.each_object

如果您阅读it's doc,它会说

ObjectSpace 模块包含许多交互的例程 使用垃圾收集设施,并允许您遍历所有 带有迭代器的活对象。

不是很清楚。但是 AFAIU 它会遍历 GC 知道的所有对象。

所以现实是这样的:这个类是不可访问的,除非你向 GC 询问它,然后它可以给你一个对它的引用。 (如果你问我,这有点骇人听闻)

IMO 你不应该在任何生产代码上信任subclasses。似乎不可预测。也许,无论你想用subclasses 实现什么,都可以用不同的方式来完成? (但这是另一个 SO 问题的主题)

【讨论】:

  • 是的,谢谢。把我的头撞在墙上。使用 subclasses 进行一些动态元编程的东西,但 def 有其他方法来做到这一点
  • 什么提示我,是这个问题:为什么一个类应该知道它的后代?从 OO 设计来看,这似乎很奇怪。此外,我所有的同事(比我聪明)都在使用 ActiveSupport。他们不太喜欢它。
猜你喜欢
  • 1970-01-01
  • 2019-07-17
  • 2016-01-01
  • 2018-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-14
相关资源
最近更新 更多