Manu
Manu

Reputation: 21

Issue with Instance variable and Rspec 2.x

I am using Rspec 2.0. I am not understanding how the scope works here... Somehow you can read the variable in any block but I cannot update it? why is that?

describe 'Test App' do
  before(:all) do
    @test= :blah
  end

  it 'test' do
    @test=:bye
    p @test  #  =>  prints bye 
  end

  it 'test' do
    p @test  #  =>  prints blah rather than bye...
  end
end

Upvotes: 2

Views: 1641

Answers (3)

Steffen Roller
Steffen Roller

Reputation: 3484

I run into the same problem and solved it with Hash in which I change values:

describe "carry over value" do
  let (:global) { Hash.new }

  before :all do
   global[:var1] = "foo"
  end

  it "should be foo" do
    global[:var1].should == "foo"
  end

  it "set to bar" do
    global[:var1] = "bar"
    global[:var1].should == "bar"
  end

  it "should still be bar" do
    global[:var1].should == "bar"
  end
end

Upvotes: 0

zetetic
zetetic

Reputation: 47578

According to the RSpec book, before(:all):

... gets run once and only once in its own instance of Object, but its instance variables get copied to each instance in which the examples are run. A word of caution in using this: in general, we want to have each example run in complete isolation from one another. As soon as we start sharing state across examples, unexpected things begin to happen.

So in your examples @blah is copied before each test is run, thus values assigned to it do not carry over from one example to another.

It seems like you want to do something like this (air code):

it "gets a token" do
  @token = OAuth.some_method_that_returns_a_token
end

it "uses that token to access some OAuth feature" do
  result = OAuth.some_feature(@token)
  result.should be_something_something
end

This smells like a test of OAuth, not of your code. You should consider stubbing out the some_feature method (more air code):

it "responds in some way when I use a valid token" do
  @token = mock('token')
  OAuth.should_receive(:some_feature).with(@token).and_return("success")
  result = my_code_which_uses_ouath(@token)
  result.should == "success"
end

Upvotes: 2

Wes
Wes

Reputation: 6585

This is really all a property of ruby and not RSpec itself. The before block is a callback invoked before each it block is executed. So that is how your variable is instantiated to blah. When in your second test your defined it to be bye that definition is redefined when the before block is invoked again for the next test.

Upvotes: 1

Related Questions