Today I Learned

A Hashrocket project

Message order constraint in RSpec

Sometimes you need to make sure your code is executing in a specific order. In the example below we have a Payment double that needs to first call processing! and then approved!. So you write a test like this:

it "approves the payment" do
  payment = double("Payment")

  expect(payment).to receive(:processing!)
  expect(payment).to receive(:approved!)

  payment.processing!
  payment.approved!
end

If you change the order of the method calls your test will still pass:

...
  payment.approved!
  payment.processing!
...

Finished in 0.01601 seconds (files took 0.20832 seconds to load)
1 example, 0 failures

To guarantee the order, RSpec has an option to specify an order constraint. So we want to make sure processing! is called before approved! :

 expect(payment).to receive(:processing!).ordered
 expect(payment).to receive(:approved!).ordered

Now if you run the test with the wrong order, you will see the error:

it "approves the payment" do
  payment = double("Payment")

  expect(payment).to receive(:processing!).ordered
  expect(payment).to receive(:approved!).ordered

  payment.approved!
  payment.processing!
end

Failure/Error: payment.approved!
   #<Double "Payment"> received :approved! out of order