Zara Kay
Zara Kay

Reputation: 164

How to stop RSpec anonymous class leaking?

So I am trying to test an abstract class. According to what I have read, give an class named Foo, I can do the following in RSpec and it won't leak in to other tests.

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

However I found that it does still leak, when I do Foo.subclasses in another location (depending on spec execution order).

I also tried to define the class the normal way and delete it in an after block, e.g.

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

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

But that also didn't seem to work. Foo.subclasses still seemed to contain the anonymous class.

Upvotes: 1

Views: 528

Answers (1)

Greg
Greg

Reputation: 6659

I did some investigations on how subclasses work, and here's what I found (though not really an answer to your question)

subclasses call internally descendants (they both come from ActiveSupport) which calls ObjectSpace.each_object

If you read it's doc, it says

The ObjectSpace module contains a number of routines that interact with the garbage collection facility and allow you to traverse all living objects with an iterator.

It's not super clear. But AFAIU it iterates over all objects that the GC knows about.

So the reality is this: this class is not reachable unless you ask GC about it, then it can give you a reference to it. (It's kind of hacky if you ask me)

IMO you should not trust subclasses on any production code. It seems unpredictable. Maybe, whatever you are trying to achieve with subclasses, could be done in a different way? (But that's a topic for another SO question)

Upvotes: 1

Related Questions