2010-10-20 62 views
4

這裏的模型規範是,我使用的模型,我已經簡化了一點下來還是失敗,我列舉了最簡單的形式:測試使用的after_create回調

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 

而且我倒要符合規範的舉例如下:

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 

其中我預計會工作得很好,但我留下了以下錯誤:

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 

任何人都可以幫助我理解爲什麼會發生這種情況嗎?

回答

4

三個問題:

1)用戶對象被設置消息的期望,所以should_receive永遠不會看到該消息之前創建的;

2)您正在爲您設定預期的方法殘缺。你想存根出方法,你組的期望,但其所需的測試通過

3)你必須在所有的參數

要修正通過,創建用戶設置expectaion後反對,並踩滅反過來每個方法(因爲你的模式要求List.create兩次):

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 

雖然這是真正的風格的問題,這讓在這裏使用一個真正的用戶對象更有意義而不是工廠,因爲你正在測試模型本身。

2

zetetic的答案很棒,但如果你想要更快一點的東西(並且仍然有效),我建議使用shoulda-callback-matchers gem。這是一套完整的匹配器,使測試回調更容易。我全部都是關於簡化&減少樣板。如果你喜歡看,你可以在我的RSpec model testing skeleton中看到一些例子。

無論哪種方式完成工作!