← Home

Expecting arbitrary method calls in a particular order in RSpec

For a spam protection feature in a project I'm currently working on I started out specifying the behaviour of a filter chain that I was planning to implement. Specifically, I wanted to specify that the filter chain would call the filters in the expected order.

Looking at the RSpec documentation for expecting method calls on mock objects I didn't found this usecase mentioned at first. It turns out to be pretty easy with RSpec mocks though.

#should_receive takes a block that (according to the documentation) is meant to be used to compute return values. This block is called within the specification's scope so it can be used to track the method call order.

My initial spec looks like this (simplified for clarity):


it "runs the filters in the correct order" do
  log = []
  @default.should_receive(:run){ log << :default }
  @akismet.should_receive(:run){ log << :akismet }
  @defensio.should_receive(:run){ log << :defensio }
  @chain.run
  log.should == [:default, :akismet, :defensio]
end

Update

After some discussion on the RSpec users mailinglist Ashley Moran pointed out a more elegant solution to this which also uses the should_receive block:


it "runs the filters in the correct order" do
@default.should_receive(:run) do
  @akismet.should_receive(:run) do
    @defensio.should_receive(:run)
  end
end
@chain.run
end

Thanks :)