Ruby 使用rspec创建后的测试

Ruby 使用rspec创建后的测试,ruby,ruby-on-rails-3,rspec,rspec2,rspec-rails,Ruby,Ruby On Rails 3,Rspec,Rspec2,Rspec Rails,我的模型中有代码 class Foo < ActiveRecord::Base after_create :create_node_for_foo def create_node_for_user FooBar.create(id: self.id) end end 但是我的测试失败了 Failures: 1) Foo create node in graph database on Failure/Error: FooBar.should_

我的模型中有代码

class Foo < ActiveRecord::Base
 after_create :create_node_for_foo

   def create_node_for_user
     FooBar.create(id: self.id)
   end
end
但是我的测试失败了

Failures:

   1) Foo create node in graph database on
      Failure/Error: FooBar.should_receive(:create).with(id: foo1.id)
      (<FooBar (class)>).create({:id=>18})
       expected: 1 time
       received: 0 times

可能出了什么问题?

好的,我们解决了这个问题

改变了这个

 it "create node in graph database" do
  foo1 = FactoryGirl.create(:foo)
  FooBar.should_receive(:create).with(id: foo1.id)
end


好吧,我有问题了

改变了这个

 it "create node in graph database" do
  foo1 = FactoryGirl.create(:foo)
  FooBar.should_receive(:create).with(id: foo1.id)
end


晚会有点晚了,但事实上,上述方法行不通。您可以创建自定义匹配器来执行此操作:

class EventualValueMatcher
  def initialize(&block)
    @block = block
  end

  def ==(value)
    @block.call == value
  end
end

def eventual_value(&block)
  EventualValueMatcher.new(&block)
end
然后在您的规范中执行以下操作:

it "create node in graph database" do
  foo1 = FactoryGirl.build(:foo)
  FooBar.should_receive(:create).with(eventual_value { { id: foo1.id } })
  foo1.save
end

这意味着模拟将在事实发生之后才对块进行评估,并且它实际上已经被设置好了。

对聚会来说有点晚,但实际上上面的方法不起作用。您可以创建自定义匹配器来执行此操作:

class EventualValueMatcher
  def initialize(&block)
    @block = block
  end

  def ==(value)
    @block.call == value
  end
end

def eventual_value(&block)
  EventualValueMatcher.new(&block)
end
然后在您的规范中执行以下操作:

it "create node in graph database" do
  foo1 = FactoryGirl.build(:foo)
  FooBar.should_receive(:create).with(eventual_value { { id: foo1.id } })
  foo1.save
end

这意味着模拟将在事实发生后才对块进行评估,并且它实际上已被设置。

如果它对某人有所帮助,则Dan Draper解决方案的更新版本将与块一起使用自定义匹配器,如下所示:

规格/支持/最终值匹配器.rb RSpec::Matchers.define:最终的_值do |预期| 匹配do |实际值| 实际==预期的.call 终止 终止 使用方法:

require support/finally_value_matcher,或者您可以在rails_helper.rb文件中执行全局require 它是xxx做的 foo1=FactoryGirl.build:foo expectFooBar.to receive:create.WithEvalueProc{foo1.id} 救命! 终止
如果对某人有帮助,Dan Draper解决方案的更新版本将使用带有块的自定义匹配器,如下所示:

规格/支持/最终值匹配器.rb RSpec::Matchers.define:最终的_值do |预期| 匹配do |实际值| 实际==预期的.call 终止 终止 使用方法:

require support/finally_value_matcher,或者您可以在rails_helper.rb文件中执行全局require 它是xxx做的 foo1=FactoryGirl.build:foo expectFooBar.to receive:create.WithEvalueProc{foo1.id} 救命! 终止
为什么这改变了什么?我重构了我的一个测试,就像你做的一样,但它仍然不起作用。你知道为什么和/或RSpec在幕后做什么吗?这与RSpec在幕后无关,只是简单的逻辑。在他更改它之前,问题是.create在.should测试之前被调用。更改后,.build用于生成记录,请记住,此时记录尚未创建。然后他打电话来。保存以实际创建记录。这就是为什么它会起作用,为什么它会改变什么?我重构了我的一个测试,就像你做的一样,但它仍然不起作用。你知道为什么和/或RSpec在幕后做什么吗?这与RSpec在幕后无关,只是简单的逻辑。在他更改它之前,问题是.create在.should测试之前被调用。更改后,.build用于生成记录,请记住,此时记录尚未创建。然后他打电话来。保存以实际创建记录。这就是它起作用的原因。