Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"nil is not a symbol" for model count in rspec matcher

I am trying to write an integration test where if a user clicks on a button, it creates a new record in the database (CheckPrice model).

I am running into the error nil is not a symbol when I try to run my test.

require 'spec_helper'

describe 'CheckPrice', type: :request, js: true  do
  it "should create a new CheckPrice record when user clicks Check Price on topic page" do
    city = create :city
    hotel = create :hotel
    affiliate_link = create :affiliate_link

    visit '/hotel-bilboa-hotel'
    sleep 2
    click_button "Check Prices"
    response.should change(CheckPrice.count).by(1)
  end
end

When "Check Prices" is clicked, there is an event listener that triggers the new method in the checkprices_controller.

The error seems to occur on the last line response.should change(CheckPrice.count).by(1). It looks like the method does not recognize the model CheckPrice. How do I reference the CheckPrice table?

Thanks.

like image 228
Huy Avatar asked Nov 05 '12 20:11

Huy


3 Answers

I don't think you can use the change matcher like this on the response object. Try this:

expect {
  click_button "Check Prices"
}.to change{ CheckPrice.count }.by(1)

This makes more semantic sense, too, IMO.

See this cheat sheet for more examples.

like image 103
Thilo Avatar answered Nov 06 '22 03:11

Thilo


Semantic aside, to answer the original question (getting "nil is not a symbol") and help other people who might land here like I did: make sure to use curly brackets {} instead of parentheses ().

So (correct)

response.should change{CheckPrice.count}.by(1)
response.should change(CheckPrice, :count).by(1)

instead of (won't work, a mix of the 2 above)

response.should change(CheckPrice.count).by(1)

Edit:

Same answer with recommended expect syntax

So (correct)

expect{response}.to change{CheckPrice.count}.by(1)
expect{response}.to change(CheckPrice, :count).by(1)

instead of (won't work, a mix of the 2 above)

expect{response}.to change(CheckPrice.count).by(1)
like image 16
Arnaud Avatar answered Nov 06 '22 03:11

Arnaud


Another way to do this would be:

expect do
    click_button "Check Prices"
end.to change(CheckPrice, :count).by(1)

Which indicates that the output of the count method on CheckPrice is what is supposed to be changing. When two parameters are passed to change, one is assumed to be a receiver, the other a symbol to send.

like image 1
Jordan Moncharmont Avatar answered Nov 06 '22 03:11

Jordan Moncharmont