在rspec中为after_create hook创建存根

时间:2013-01-01 16:23:32

标签: ruby ruby-on-rails-3 rspec rspec2 rspec-rails

我的型号代码是:

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})

可能出现什么问题?

2 个答案:

答案 0 :(得分:3)

Yves给出的解释是正确的:用户ID为nil,直到保存记录为止,因为它是由DB自动生成的。这是另一种方法:

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时。

答案 1 :(得分:2)

问题是您使用FactoryGirl构建的userr没有ID。这就是为什么期望告诉你你期望:user_id=>nil。 AR保存记录时将生成ID,因此您无法提前猜出生成的ID。您可以在模拟上使用限制较少的断言:

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

这将验证是否使用:user_id密钥传递散列。您可以在此处找到有关hash_including的更多信息:http://rubydoc.info/gems/rspec-mocks/RSpec/Mocks/ArgumentMatchers:hash_including

你可以尝试的另一件事(不确定它是否有效)是匹配rspec的kind_of匹配器。这样可以确保使用:user_id

传递了一个数字
UserGraph.should_receive(:create).with(:user_id => kind_of(Numeric))