Testing

Testing for non existing records with Rails


Sometimes you want to test how your code behaves when a record cannot be found, for example when testing the ‘unhappy’ path.

There are several ways to approach this. You could use a random, high id that you assume to not exist in your test database, since it’s cleaned after every test right!

it "returns false when the post cannot be found" do
  expect(widget.perform(post_id: 100_000)).to eq false
end

This probably works fine. But it assumes a couple of things:

  1. That no record exists with that id.
  2. That the test database is actually cleaned after every test.
  3. That no other records are created in this test.
  4. That 100,000 is high enough to not have been used, if there are other records.
  5. That other people reading this code later understand what the 100,000 actually means.

It’s much better to actually stub out the model to ensure it returns the right error.

In case the underlying widget class uses Post.find to grab the record, you could stub it like this:

allow(Post).to receive(:find).and_raise(ActiveRecord::RecordNotFound)

if it uses Post.where(id: ...).first you can use something like:

Post.stub_chain(:where, :first).and_return(nil)

If your class uses a specific method to grab the record (like in a before_action), you can stub that method.