Crash Test Dummy

What?

A Crash Test Dummy is an object that we have created to fail in a specific — and spectacular — way.

Why?

We're our own error handling code around a third party API, file system, or similar with well defined but difficult to reproduce failure modes. How do you force someone elses' API to return a given error code, for example, or test that your application gracefully handles a full hard disk without filling the hard disk with trash data?

How?

We can make a crash test dummy by mocking or stubbing the object that does the actual system interaction and forcing it to raise a certain exception. This allows us to test the error handling in our code without performing extreme acts.

require 'net/http'

# Our API client. It performs HTTP interactions, it (usually) works, but it
# doesn't do any error handling of its own.
class MyApiClient
  def read_from_endpoint
    :some_good_stuff_returned_from_the_api
  end
end

# The class under test. This class consumes data from the API using the
# API client, and we want to ensure that our rescue block behaves as
# expected.
class ApiConsumer
  def pull_data
    response = MyApiClient.new.read_from_endpoint
  rescue Net::ReadTimeout
    response = :read_timeout_failure
  ensure
    response
  end
end

RSpec.describe ApiConsumer do
  it 'handles read timeouts from the api' do
    # We're using a stubbed method to implement our crash test dummy.
    expect_any_instance_of(MyApiClient).to receive(:read_from_endpoint)
                                             .and_raise(Net::ReadTimeout)

    consumer = ApiConsumer.new
    expect(consumer.pull_data).to eq(:read_timeout_failure)
  end
end