Testing Error Scenarios in Rails Applications
Rails' testing ecosystem makes error scenario testing straightforward. Here's how to cover failure paths with RSpec.
Controller Error Tests
RSpec.describe Api::V1::UsersController, type: :request do
describe 'GET /api/v1/users/:id' do
it 'returns 404 when user not found' do
get '/api/v1/users/nonexistent'
expect(response).to have_http_status(:not_found)
expect(json_response['error']).to include('not found')
end
it 'returns 401 when not authenticated' do
get '/api/v1/users/1'
expect(response).to have_http_status(:unauthorized)
end
end
describe 'POST /api/v1/users' do
it 'returns 422 with validation errors' do
post '/api/v1/users', params: { user: { email: 'invalid' } },
headers: auth_headers
expect(response).to have_http_status(:unprocessable_entity)
expect(json_response['details']).to include(/Email is invalid/)
end
end
endModel Validation Tests
RSpec.describe Order, type: :model do
describe 'validations' do
it 'rejects negative quantities' do
order = build(:order, quantity: -1)
expect(order).not_to be_valid
expect(order.errors[:quantity]).to include('must be greater than 0')
end
it 'enforces uniqueness of order number' do
create(:order, order_number: 'ORD-001')
duplicate = build(:order, order_number: 'ORD-001')
expect(duplicate).not_to be_valid
end
end
endService Object Error Tests
RSpec.describe CreateOrder do
it 'handles payment gateway timeout' do
allow(PaymentGateway).to receive(:charge)
.and_raise(Net::OpenTimeout)
result = described_class.new.call(valid_params)
expect(result.success).to be false
expect(result.error).to include('timeout')
end
it 'rolls back on partial failure' do
allow(InventoryService).to receive(:reserve)
.and_raise(InventoryService::OutOfStock)
expect { described_class.new.call(valid_params) }
.not_to change(Order, :count)
end
endBackground Job Error Tests
RSpec.describe ProcessOrderJob, type: :job do
it 'retries on timeout errors' do
allow(OrderProcessor).to receive(:process!)
.and_raise(Net::OpenTimeout)
expect {
described_class.perform_now(order.id)
}.to have_enqueued_job(described_class)
end
it 'discards when order not found' do
expect {
described_class.perform_now('deleted-id')
}.not_to raise_error
end
endEach production error caught by Bugsly should inspire a new test. This feedback loop ensures your test suite grows with real-world failure patterns.
Try Bugsly Free
AI-powered error tracking that explains your bugs. Set up in 2 minutes, free forever for small projects.
Get Started FreeRelated Articles
How to Set Up Bugsly in Flask
Learn how to set up error monitoring in Flask with Bugsly. Step-by-step guide with code examples and best practices.
Read more.NET Alerting: Complete Setup Guide
Complete guide to integrating Bugsly alerting in your .NET project. Get started in minutes with this tutorial.
Read moreSetting Up Bugsly in Your Ruby on Rails Project
Add error monitoring to your Ruby on Rails app with Bugsly. Covers installation, SDK setup, and production best practices.
Read moreHow to Set Up Bugsly in React
Step-by-step tutorial for configuring Bugsly error monitoring in React. Includes code snippets and optimization tips.
Read more