1

I am trying to refactor a spec that currently passes or fails based off the order in which the examples are run.

Spec is below.

If the first example runs first, the spec passes.

If the second test runs before the first, it fails. I understand why it fails -- there are three subclasses of FieldExtractor in ObjectSpace so the assertion expect(FieldExtractor.all.size).to eq 2 will be false.

RSpec.describe FieldExtractor do

  it 'keeps track of subclasses' do
    class TotalExtractor < FieldExtractor
    end
    class VendorExtractor < FieldExtractor
    end

    expect(FieldExtractor.all).to include(TotalExtractor)
    expect(FieldExtractor.all).to include(VendorExtractor)
    expect(FieldExtractor.all.size).to eq 2
  end

  it 'keeps track of extracted field' do
    class ConfiguredExtractor < FieldExtractor
      extracts :vendor
    end

    expect(ConfiguredExtractor.field).to eq :vendor
  end
end

My question is how to fix this intermittant test failure.

Is there an elegant way around this? Is the way I'm testing this totally off-base?

One solution I got working but don't particularly care for is defining all the subclasses at the beginning of the spec (outside the examples) so that I know exactly how many there should be. I don't like this solution because I have many examples with many subclasses and it doesn't seem to scale well.

madcow
  • 2,567
  • 14
  • 31
  • `before(:each) { FieldExtractor.clear }` where the implementation of `clear` is up to you (might be [assigning constant to `nil`](http://stackoverflow.com/a/3424706/2035262).) My experience says that you’ll nevertheless have it (`#clear`) sooner or later required. – Aleksei Matiushkin Sep 25 '15 at 16:42

1 Answers1

1

You may use stub_const to stub an undefined const, that will be automatically removed after test execution:

it 'keeps track of subclasses' do
  stub_const('TotalExtractor', Class.new(FieldExtractor))
  stub_const('VendorExtractor', Class.new(FieldExtractor))

  expect(FieldExtractor.all).to include(TotalExtractor)
  expect(FieldExtractor.all).to include(VendorExtractor)
  expect(FieldExtractor.all.size).to eq 2
end
Alexey Shein
  • 7,342
  • 1
  • 25
  • 38