Rspec应该接受无序检查

时间:2013-07-05 17:47:53

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

目前,如果您有一个多次调用的方法,并且您希望确保发生某个调用,那么您需要编写大量虚拟代码。

events = []
Analytics.should_receive(:track) do |event|
  events << event
end.any_number_of_times

<<INVOKE CONTROLLER ACTION>>

event = events.find{|event| event.event_name == 'MyEventName'}
event.should_not be_nil
event.properties.should include({ property_a: value})

需要上面的代码 1.记录被跟踪的所有事件 2.找到特定事件名称的至少一个实例并匹配属性

当应该采用更简单的方法时,会产生大量代码。

Analytics.should_receive(:track) do |event|
  expect(event.event_name).to eq('MyEventName')
  expect(event.properties).to include({ property_a: value})
end.at_least(:once)

不幸的是,只有在第一次调用Analytics.track导致匹配时,上述操作才有效。如果是第二次调用,则此测试将失败。

我有自己的解决方案试图让它变得通用且可重复使用但我想知道是否有一种简单的方法可以实现这一点,我可能会失踪。

2 个答案:

答案 0 :(得分:1)

您可以尝试将预期的确切事件传递给with。这里的关键是在调用track之前存根should_receive

这是一个示例代码:

require 'ostruct'

class Analytics
  def self.run
    track(OpenStruct.new(event_name: 'test1', properties: { a: '1' }))
    track(OpenStruct.new(event_name: 'test2', properties: { a: '2' }))
  end

  def self.track(event)
  end
end

describe Analytics do
  it 'verifies the second event' do
    expected_event = OpenStruct.new(event_name: 'test2', properties: { a: '2' })

    Analytics.stub(:track)
    Analytics.should_receive(:track).with(expected_event)

    Analytics.run
  end
end

答案 1 :(得分:1)

OP应该“接受”前面的答案,因为它包含两个关键元素并且首先出现,但是这里有一个更简洁的例子(它也使用了最新的expect方法),以防它有助于使rspec的能力更加清晰:

describe "unordered checks" do
  it 'verifies the second method call' do
    obj = Object.new
    obj.stub(:track)
    expect(obj).to receive(:track).with('expected')
    obj.track('unexpected')
    obj.track('expected')
  end
end

我会把这个编辑成上一个答案,但认为这会占用过多的许可证。