Netskin Logo

RSpec Quick Tip - be_done?

#rails
#rspec
by Tom Rothe on 23.08.2022

Sometimes in an RSpec example, we need to check if a certain action was done by verifying the resulting state. The following example runs a service and expects that a result record was created:

it 'does the thing' do
  Thing.run
  expect(Result.count).to eq(1) # check if the thing was done
end

This does not tell the right story. We do not want to check for the count of result; we want to check if the service was done. We could improve the story by defining a helper method:

it 'does the thing' do
  Thing.run
  expect_thing_was_done
end

def expect_thing_was_done
  expect(Result.count).to eq(1)
end

This shows the intention much better, but it does not fit to the usual RSpec schema: expect(A).to matcher(B). With a little trick we can get the right story while keeping true to the RSpec syntax:

it 'does the thing' do
  Thing.run
  expect(thing).to be_done
end

def thing
  OpenStruct.new(done?: Result.count == 1)
end

RSpec’s be_* matchers automatically check for truth in the corresponding attribute by appending a question mark to the matcher’s name.

Happy Coding!

❮ Pattern matching and deconstructing
Ruby arrays cheatsheet ❯
Netskin Logo