23

I often want to do

context "empty stack" do
  SOME_CONSTANT = "value"
  it "should be empty" do
    # use SOME_CONSTANT
  end
end

context "populated stack" do
  SOME_CONSTANT = "a different value"
  it "should have some items" do
    # use SOME_CONSTANT
  end
end

ruby doesn't scope constants to closures so they leak out. Does anyone have a trick for declaring constants that are scoped to a context?

Shad
  • 15,134
  • 2
  • 22
  • 34
opsb
  • 29,325
  • 19
  • 89
  • 99

3 Answers3

30

Change the declaration of the constant:
from SOME_CONSTANT = "value"
to self::SOME_CONSTANT = "value"

RSpec creates an anonymous class for each set of specs (context in your example) that it comes across. Declaring a constant without self:: in an anonymous class makes it available in global scope, and is visible to all the specs. Changing the constant declaration to self:: ensures that it is visible only within the anonymous class.

Nakilon
  • 34,866
  • 14
  • 107
  • 142
naren
  • 348
  • 4
  • 9
25

Having used rspec for longer now I think the more idiomatic approach is to use let.

context "empty stack" do
  let(:some_constant){ "value" }

  it "should be empty" do
    puts some_constant
  end
end

context "populated stack" do
  let(:some_constant){ "a different value" }

  it "should have some items" do
    puts some_constant
  end
end
opsb
  • 29,325
  • 19
  • 89
  • 99
  • 3
    I totally recommend using the `let` constructs. Read more about `let` here: https://www.relishapp.com/rspec/rspec-core/docs/helper-methods/let-and-let – Nicolas Feb 18 '14 at 16:32
  • I want to use `let` but it's not available in the before blocks. – 23inhouse Apr 04 '16 at 07:50
  • That's not true. Definitions with `let` are available in `before`, `before(:each)` and `before(:suite)`. They only don't work with `before(:all)`. – brainbag Jul 27 '17 at 18:22
  • `before(:all)` exact the case why I am here :) – x'ES Jun 11 '20 at 05:29
2

The correct way to do it is to use stub_const

RSpec.describe "stubbing FOO" do
  it "can stub undefined constant FOO" do
    stub_const("FOO", 5)
    expect(FOO).to eq(5)
  end

  it "undefines the constant when the example completes" do
    expect { FOO }.to raise_error(NameError)
  end
end

https://relishapp.com/rspec/rspec-mocks/v/3-9/docs/mutating-constants/stub-undefined-constant

TheGeorgeous
  • 3,927
  • 2
  • 20
  • 33