如何在rspec中测试方法调用的顺序?

Dan*_*arp 13 ruby testing rspec

我有一个使用命令模式的类按顺序执行一系列简单的转换步骤.数据作为数据馈送(以XML格式)传入,然后使用单一用途的步骤类通过多个步骤进行转换.所以它可能看起来像这样(实际的类名不同):

raw_data = Downloader.new(feed)
parsed_data = Parser.new(raw_data)
translated_data = Translator.new(parsed_data)
sifted_data = Sifter.new(translated_data)
collate_data = Collator.new(sifted_data)
Run Code Online (Sandbox Code Playgroud)

等等

我有每个类的单元测试,我有集成测试来验证完整的流程,包括调用每个类.

但我没有办法测试他们被称为的顺序

我想要一些测试,所以我可以知道:首先调用Downloader,然后是Parser,然后是Translator等.

这是Ruby与Rspec 3.

我确实找到了这个:http://testpractices.blogspot.com/2008/07/ordered-method-testing-with-rspec.html但这是从2008年开始,它也非常难看.有没有更好的方法来测试方法执行顺序?

谢谢!

ama*_*hah 15

RSpec Mocks ordered至少提供RSpec 3.0:

您可以使用ordered约束多个消息期望的顺序.这通常不推荐使用,因为在大多数情况下,顺序无关紧要,使用有序会使您的规格变得脆弱,但它偶尔会有用.当您使用ordered时,只有在声明的订单中收到消息时,示例才会通过.

请注意,RSpec同意@spickermann认为这不是推荐的做法.但是,在某些情况下有必要,特别是在处理遗留代码时.

这是RSpec传递的例子:

RSpec.describe "Constraining order" do
  it "passes when the messages are received in declared order" do
    collaborator_1 = double("Collaborator 1")
    collaborator_2 = double("Collaborator 2")

    expect(collaborator_1).to receive(:step_1).ordered
    expect(collaborator_2).to receive(:step_2).ordered
    expect(collaborator_1).to receive(:step_3).ordered

    collaborator_1.step_1
    collaborator_2.step_2
    collaborator_1.step_3
  end
end
Run Code Online (Sandbox Code Playgroud)

失败的例子:

RSpec.describe "Constraining order" do
  it "fails when messages are received out of order on one collaborator" do
    collaborator_1 = double("Collaborator 1")

    expect(collaborator_1).to receive(:step_1).ordered
    expect(collaborator_1).to receive(:step_2).ordered

    collaborator_1.step_2
    collaborator_1.step_1
  end

  it "fails when messages are received out of order between collaborators" do
    collaborator_1 = double("Collaborator 1")
    collaborator_2 = double("Collaborator 2")

    expect(collaborator_1).to receive(:step_1).ordered
    expect(collaborator_2).to receive(:step_2).ordered

    collaborator_2.step_2
    collaborator_1.step_1
  end
end
Run Code Online (Sandbox Code Playgroud)