How can I test a model with rspec that has after_create callback

2.3k Views Asked by At

I have this model

class User < ActiveRecord::Base
  after_create :create_in_remote

  def create_in_remote
   if self.remote_id.nil?
    req_url = "api/create/user/#{self.username}"
    response = Remote.execute_request(req_url)
    if response
      self.update_attribute(:remote_id, response["id"]) if response["id"]
    end
   end
  end
end

In my spec I try to do this

require 'spec_helper'

describe User do
  before { @user = FactoryGirl.build(:user) }

  subject { @user }


  it "has_remote_id" do
    @user.save! && @user.reload
    expect(@user.remote_id).not_to be_nil
  end
end

but never passes the test but the object is always created on the remote api. If I want to see the value of the attribute remote_id of the @user object is always null. If I change build to create in the factory, i can see in the log that the attribute is updated, but when use in the test it is null and fail the test.

3

There are 3 best solutions below

0
benjaminjosephw On

The syntax in your test looks wrong. Rspec introduced the expect syntax so that instead of this:

foo.should eq(bar)
foo.should_not eq(bar)

you can do this:

expect(foo).to eq(bar)
expect(foo).not_to eq(bar)

You're mixing expect with should so I imagine this is causing your test to fail.

Here's a good blog post about Rspec's new expectation syntax

0
gotva On

You should change expectation as @benjaminjosephw suggests.

But I think you have another problem in your spec. When you create user it is really has remote_id equals to nil (I mean after building but before creating). When you create user you update attribute remote_id in DB but your object user still does not have this value. You should reload object to fetch this data from DB.

before { @user = FactoryGirl.build(:user) }

it "has_remote_id" do
  @user.save! && @user.reload
  expect(@user.remote_id).not_not be_nil
end
0
user1179871 On

Try this to ensure that the callback is called and expect(user.remote_ip).to eq(...) - to check remote_ip

describe 'after_create' do
  before { @user = User.new }
  it 'run the create_in_remote callback' do
    expect(@user).to receive(:create_in_remote) 
    @user.run_callbacks(:create) 
  end
end