kdweber89
kdweber89

Reputation: 2174

How to pass both an object with a message in rspec?

I'm having trouble trying to write a test for an app that I help contribute to. I will admit upfront that my talents are definitely on the front end of development and so when it comes to rpsec testing, i'm not the greatest.

I am basically creating a test for a location, and I have an admin is able to create a new location. I also created a factory for these locations. Ultimately the problem that I am getting is when I try to increase the count level of a location up by 1. I wind up with an error stating

'change' requires either an object and message ('change(obj, :msg)') or a block ('change { }'). You passed an object but no message.

I really don't know what I can do to get around this, and so i'm wondering if anybody could take a gander and what i've done.

Here is my factory:

FactoryGirl.define do
 factory :location do |c|
  c.name 'sample location'
  c.phone '5555555555'
  c.fax '5555555555'
  location_id '123456'
  association :address, factory: :address
end

Here is my spec.

require 'spec_helper'

describe Admin::LocationController, type: :controller do
 before(:all) do
   @admin = create(:admin)
   @location = create(:location)
 end

after(:all) do
  @admin.destroy
  @location.destroy
end

let(:admin) {@admin}
let(:location) {@location}

before(:each) do
  sign_in(:user, admin)
end

describe '#create' do
  it 'creates a new location' do

    expect{
      post :create, location:{
        name: 'sample location',
        phone: '5555555555',
        fax: '5555555555',
        location_id: '123456',

        address_attributes: {
          address1: '12345 Some St',
          city: 'Portland',
          state: 'OR',
          zip: '91237'
        }
      }
    }.to change(Location.count).by(1)

    new_location = Location.last
    expect(new_location.name).to eq 'sample location'
    expect(new_location.phone).to eq '5555555555'
    expect(new_location.fax).to eq '5555555555'
    expect(new_location.location_id). to eq '123456'
    expect(new_location.address.address1).to eq '12345 Some St'
    expect(new_location.address.city).to eq 'Portland'
    expect(new_location.address.state).to eq 'OR'
    expect(new_location.address.zip).to eq '91237'
   end
 end
end

Upvotes: 3

Views: 1663

Answers (3)

Maxim Pontyushenko
Maxim Pontyushenko

Reputation: 3043

The error says exactly what you need to do – to put object that is changing in {} brackets. This could help:

require 'spec_helper'

    describe Zipadmin::LocationController, type: :controller do
     before(:all) do
       @admin = create(:admin)
       @location = create(:location)
     end

    after(:all) do
      @admin.destroy
      @location.destroy
    end

    let(:admin) {@admin}
    let(:location) {@location}

    before(:each) do
      sign_in(:user, admin)
    end

    describe '#create' do
      it 'creates a new location' do

        expect{
          post :create, location:{
            name: 'sample location',
            phone: '5555555555',
            fax: '5555555555',
            location_id: '123456',

            address_attributes: {
              address1: '12345 Some St',
              city: 'Portland',
              state: 'OR',
              zip: '91237'
            }
          }
        }.to change{Location.count}.by(1)

        new_location = Location.last
        expect(new_location.name).to eq 'sample location'
        expect(new_location.phone).to eq '5555555555'
        expect(new_location.fax).to eq '5555555555'
        expect(new_location.ncpdp_id). to eq '123456'
        expect(new_location.address.address1).to eq '12345 Some St'
        expect(new_location.address.city).to eq 'Portland'
        expect(new_location.address.state).to eq 'OR'
        expect(new_location.address.zip).to eq '91237'
       end
     end
    end

Upvotes: -1

PhilVarg
PhilVarg

Reputation: 4811

The error is telling you that you're passing incorrect arguments to the change method. The change method requires a block be passed to it.

}.to change { Location.count }.by(1)

It also mentions an alternate syntax of passing it an object/model (Location) and a message (a method to call in symbol format, in this case :count)

}.to change(Location, :count).by(1)

Upvotes: 1

Cristiano Mendonça
Cristiano Mendonça

Reputation: 1282

Try this:

}.to change(Location, :count).by(1)

OR

}.to change { Location.count }.by(1)

instead of

}.to change(Location.count).by(1)

Upvotes: 6

Related Questions