Bhushan Lodha
Bhushan Lodha

Reputation: 6862

creating stub for after_create hook in rspec

my model code is:

class User < ActiveRecord::Base
  after_create :create_node_for_user

   def create_node_for_user
     UserGraph.create(user_id: self.id)
   end
end

and test for User model:

it "create node in graph database on user creation" do
  userr = FactoryGirl.build(:user)
  UserGraph.should_receive(:create).with(user_id: userr.id)
  userr.save
end

but my test is failing with message

Failure/Error: userr.save
   <UserGraph (class)> received :create with unexpected arguments
     expected: ({:user_id=>nil})
          got: ({:user_id=>94})

what might be wrong?

Upvotes: 2

Views: 1390

Answers (2)

Myron Marston
Myron Marston

Reputation: 21810

The explanation given by Yves is correct: the user id is nil until the record is saved because it is autogenerated by the DB. Here's an alternate approach:

it "create node in graph database on user creation" do
  userr = FactoryGirl.build(:user)

  create_args = nil
  UserGraph.should_receive(:create) { |*args| create_args = args }
  userr.save

  expect(create_args).to eq(:user_id => userr.id)
end

Essentially, this moves the expectation about what the arguments should be so that it comes after the record has been saved, when the record has an id.

Upvotes: 3

Yves Senn
Yves Senn

Reputation: 1996

The Problem is that the userr you build with FactoryGirl does not have an ID. Thats why the expectation tells you that you expected :user_id=>nil. The ID will be generated when AR saves the record, so there is no way that you can guess the generated ID ahead of time. You could use a less restrictive assertion on the mock:

UserGraph.should_receive(:create).with(hash_including(:user_id))

This will verify that a hash is passed with a :user_id key. You can find more about hash_including here: http://rubydoc.info/gems/rspec-mocks/RSpec/Mocks/ArgumentMatchers:hash_including

Another thing you can try (not sure if it works) is to match against the kind_of matcher of rspec. This would make sure that a number was passed with :user_id

UserGraph.should_receive(:create).with(:user_id => kind_of(Numeric))

Upvotes: 2

Related Questions