RSpec期望接收带数组的方法,但顺序无关紧要

Fil*_*uzi 9 ruby arrays rspec ruby-on-rails ruby-on-rails-4

假设我有一个方法#sum,它接受一个数组并计算所有元素的总和.我正在抄袭它:

  before do
    expect(calculation_service).to receive(:sum?).with([1, 2, 3]) { 6 }
  end
Run Code Online (Sandbox Code Playgroud)

不幸的是,我的测试服以随机顺序传递数组.由于该错误被提出:

 Failure/Error: subject { do_crazy_stuff! }
   #<InstanceDouble() (CalculationService)> received :sum? with unexpected arguments
     expected: ([1, 2, 3])
          got: ([3, 2, 1])
Run Code Online (Sandbox Code Playgroud)

是否有可能对方法调用忽略数组元素的顺序?array_including(1, 2, 3)不确定数组大小,所以它可能不是最好的解决方案

Myr*_*ton 14

您可以将任何RSpec匹配器传递给with,并contain_exactly(1, 2, 3)完全按照您的意愿执行,因此您可以将其传递给:

expect(calculation_service).to receive(:sum?).with(contain_exactly(1, 2, 3)) { 6 }
Run Code Online (Sandbox Code Playgroud)

但是,"正好包含1,2,3"并不能很好地读取(并且失败消息在语法上也同样笨拙),因此RSpec 3提供了解决这两个问题的别名.在这种情况下,您可以使用a_collection_containing_exactly:

expect(calculation_service).to receive(:sum?).with(
  a_collection_containing_exactly(1, 2, 3)
) { 6 }
Run Code Online (Sandbox Code Playgroud)

  • 如果要将数组传递给 contains_exactly,请记住将其展开,例如“expect(calculation_service).to receive(:sum?).with(contain_exactly(*my_array))” (5认同)

小智 5

也可以使用方法match_array。这样,您不需要首先拆分数组的元素;相反,您可以只使用整个数组来匹配。

所以你可以使用:

expect(calculation_service).to receive(:sum?).with(match_array([1, 2, 3])) { 6 }
Run Code Online (Sandbox Code Playgroud)