Testing the specification of a model using the after_create callback

Here is the model I'm using, I simplified it a bit to the simplest form, which still does not match my example:

class User < ActiveRecord::Base after_create :setup_lists def setup_lists List.create(:user_id => self.id, :name => "current") List.create(:user_id => self.id, :name => "master") end end 

And I would like to give an example as follows:

 require 'spec_helper' describe User do before(:each) do @user = Factory(:user) end describe "#setup_lists" do before(:each) do List.stub(:create).with(:name => "current") List.stub(:create).with(:name => "master") it "creates a new master list" do List.should_receive(:create).with(:name => "master") end it "creates a new current list" do List.should_receive(:create).with(:name => "current") end end end 

I expected this to be normal, but I was left with the following error:

 Failures: 1) User#setup_lists creates a new master list Failure/Error: List.should_receive(:create).with(:name => "current") (<List(id: integer, name: string, created_at: datetime, updated_at: datetime, user_id: integer) (class)>).create({:name=>"current"}) expected: 1 time received: 0 times # ./spec/models/user_spec.rb:44 2) User#setup_lists creates a new current list Failure/Error: List.should_receive(:create).with(:name => "master") (<List(id: integer, name: string, created_at: datetime, updated_at: datetime, user_id: integer) (class)>).create({:name=>"master"}) expected: 1 time received: 0 times # ./spec/models/user_spec.rb:48 

Can someone help me understand why this is happening?

+4
source share
2 answers

Three questions:

1) A custom object is created before the expected message is set, so should_receive will never see the message;

2) You create methods for which you also set expectations. You want to disable methods for which you do not set expectations, but which are necessary to pass the test.

3) You need to pass all the parameters

To fix, create a User object after installing expectaion and align each method one at a time (because your model calls List.create twice):

 describe User do describe "#setup_lists" do it "creates a new master list" do List.stub(:create).with(:user_id=>1,:name => "current") List.should_receive(:create).with(:user_id=>1,:name => "master") @user = User.create end it "creates a new current list" do List.stub(:create).with(:user_id=>1,:name => "master") List.should_receive(:create).with(:user_id=>1,:name => "current") @user = User.create end end end 

While this is really a style issue, it makes sense to use a real User object here rather than a factory, since you are testing the model itself.

+4
source

zetetic answer is awesome, but if you need something a little faster (and still work), I would recommend using a musta-callback-matchers gem . This is a complete set of helpers that make it easy to test callbacks. I’m all about the light and reducing template. You can see some examples in my skeleton for testing the RSpec model if you want to look.

In any case, the work is done!

+2
source

All Articles