2013-01-01 81 views
2

我的模型代碼是:創建存根rspec的

class User < ActiveRecord::Base 
    after_create :create_node_for_user 

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

和測試用戶模式:

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 

,但我的測試與消息

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

沒有什麼可能是錯的?

+0

會記錄什麼? –

回答

2

問題是您使用FactoryGirl生成的userr沒有ID。這就是爲什麼期望告訴你,你期望:user_id=>nil。 AR在保存記錄時將生成ID,因此您無法提前猜測生成的ID。你可以在模擬使用限制較少的斷言:

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

這將確認散列與:user_id關鍵過去了。您可以在這裏找到更多關於hash_includinghttp://rubydoc.info/gems/rspec-mocks/RSpec/Mocks/ArgumentMatchers:hash_including

另一件事你可以嘗試(不知道它的工作原理)是匹配對kind_of匹配的RSpec的。這將確保一些與:user_id

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

通過由Yves給出的解釋是正確的:用戶ID是零,直到在保存記錄,因爲它是由數據庫自動生成。這裏有一個替代方法:

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 

本質上講,這對移動的論點應該是什麼,這樣說到後的記錄已被保存,當記錄有一個id的期望。

+0

你能解釋一下這行嗎UserGraph.should_receive(:create){| * args | create_args = args}' –

+0

是的。該塊是一種用任意代碼處理'create'消息的方法(請參閱https://github.com/rspec/rspec-mocks#arbitrary-handling)。當'UserGraph'收到'create'消息時,它將運行提供的塊。在該塊中,我將'create'消息提供的參數存儲在局部變量中,以便稍後在示例結束時設置期望值。 –