Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSpec expect to receive method with array but order does not matter

Lets say I have method #sum which takes an array and calculates sum of all elements. I'm stubbing it:

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

unfortunately my test suit passes array in random order. Because of that error is raised:

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

Is it possible to stub method call ignoring order of an array elements? array_including(1, 2, 3) does not ensure about array size, so it probably is not the best solution here

like image 968
Filip Bartuzi Avatar asked Nov 06 '15 12:11

Filip Bartuzi


2 Answers

You can pass any RSpec matcher to with, and contain_exactly(1, 2, 3) does exactly what you want, so you can pass that to with:

expect(calculation_service).to receive(:sum?).with(contain_exactly(1, 2, 3)) { 6 }

However, "with contain exactly 1, 2, 3" doesn't read very well (and the failure message will be similarly grammatically awkward), so RSpec 3 provides aliases that solve both problems. In this case, you can use a_collection_containing_exactly:

expect(calculation_service).to receive(:sum?).with(
  a_collection_containing_exactly(1, 2, 3)
) { 6 }
like image 197
Myron Marston Avatar answered Oct 24 '22 05:10

Myron Marston


You can also use the method match_array. This way, you don't need to first split the elements of the array; instead, you can just use the whole array to match.

So you can use:

expect(calculation_service).to receive(:sum?).with(match_array([1, 2, 3])) { 6 }
like image 2
Oliver Kristen Avatar answered Oct 24 '22 06:10

Oliver Kristen