35
votes

I'm trying to check that a new action in my RESTful controller set up an instance variable of the required Object type. Seems pretty typical, but having trouble executing it

Client Controller

def new
  @client = Client.new
end  

Test

describe "GET 'new'" do
  it "should be successful" do
    get 'new'
    response.should be_success
  end

  it "should create a new client" do
    get 'new'
    assigns(:client).should == Client.new
  end
end

Results in...

'ClientsController GET 'new' should create a new client' FAILED
  expected: #,
       got: # (using ==)

Which is probably because it's trying to compare 2 instances of active record, which differ. So, how do I check that the controller set up an instance variable that holds a new instance of the Client model.

3

3 Answers

37
votes

technicalpickles in #rspec helped me out...

assigns(:client).should be_kind_of(Client)
16
votes

You can use Rails' new_record? method to check if a given instance has been saved to the database already or not:

assigns(:client).should be_a(Client)
assigns(:client).should be_new_record

(You can't use assigns[:client] for historical reasons, according to: http://guides.rubyonrails.org/testing.html#the-four-hashes-of-the-apocalypse)

15
votes

For that 2016 RSpec v3 syntax use:

expect(assigns(:client)).to be_a(Client)

Also, for others that may stop here because of the question title, here is how to test if an instance variable @client was set to anything

# in controller action
@client = Client.find_by(name: "John")

# spec assignment based on collection membership

expect(assigns.keys).to include('client')

See @Attila Györffy's answer about why the assigns hash must be accessed with string keys.