How do instance variables in rspec work?

TradeRaider picture TradeRaider · Sep 28, 2012 · Viewed 18.5k times · Source

Here is a bit of code from M Hartl's Ruby on Rails Tutorial. Can anyone explain why an instance variable (@user) is necessary and why not use a local variable. Also, since instance variables are supposed to be the variables in the instance of a class, which class is @user instantiated from?

require 'spec_helper'

describe User do

  before { @user = User.new(name: "Example User", email: "[email protected]") }

  subject { @user }

  it { should respond_to(:name) }
  it { should respond_to(:email) }
end

Answer

peakxu picture peakxu · Sep 28, 2012

Use of a local variable in that instance would mean that its scope would be restricted to the before and hence result in an error. The @user is of type User but is an instance variable of the describe block. Rspec has some magic that at run-time makes a class out of each describe block. Each example (it block) ends up being a subclass of said class. Class inheritance lets the examples see @user.

Edited 2017-05-14

Linked blog post is no longer available. Updating with Wayback Machine link + inlining relevant section here.

Note that this is considered an anti-pattern as detailed in this blog post. Use let instead.

let has the following advantages:

  • It is memoized when used multiple times in one example, but not across examples.
  • It is lazy-loaded, so you wont waste time initializing the variable for examples that don't reference it.
  • Will raise an exception if you have a typo in your variable name.