Skip to content

RSpec Integration

Roman Samoilov edited this page Jan 26, 2026 · 3 revisions

Note

This wiki page is no longer maintained. The RSpec documentation has moved to the official docs site: https://rage-rb.dev/docs/rspec


Rage exposes the following methods to allow you to test your API endpoints:

  get(path, params: {}, headers: {})
  options(path, params: {}, headers: {})
  head(path, params: {}, headers: {})

  post(path, params: {}, headers: {}, as: nil)
  put(path, params: {}, headers: {}, as: nil)
  patch(path, params: {}, headers: {}, as: nil)
  delete(path, params: {}, headers: {}, as: nil)

Additionally, the have_http_status matcher is available to test the response status.

This API is only available inside the request specs after requiring rage/rspec.

Setting up a project

Follow these steps to set up RSpec in your new Rage project.

1. Add dependencies

Add the following lines to your Gemfile:

group :test do
  gem "rspec"
  gem "database_cleaner-active_record"
end

The code above suggests that you use Active Record as an ORM. If you are using a different ORM, ensure you use an appropriate adapter.

2. Init RSpec

Run the following command in your terminal to set up RSpec and create the necessary configurations:

$ rspec --init

3. Configure Database Cleaner

Add the following lines inside the RSpec.configure block in spec/spec_helper.rb:

config.before(:suite) do
  DatabaseCleaner.strategy = :truncation
end

config.around(:each) do |example|
  DatabaseCleaner.cleaning(&example)
end

Here, we define two hooks:

  • the before(:suite) hook configures Database Cleaner to use the truncation strategy;
  • the around(:each) hook ensures each example runs on a clean database;

ℹ️ The transaction cleaning strategy is currently not supported. This is because it relies on Database Cleaner starting a transaction on a connection and expecting the same connection to be used to create the records and query them in the controller. However, Rage executes requests in separate Fibers, causing Active Record to use different connections for the test and the controller, thus breaking this expectation.

4. Create the first test

require "rage/rspec"

RSpec.describe "my first test", type: :request do
  it "works!" do
    get "/"

    expect(response).to have_http_status(:ok)
    expect(response.parsed_body).to eq("It works!")
  end
end

Examples

Testing the response

require "rage/rspec"

RSpec.describe Api::V1::PhotosController, type: :request do
  describe "#index" do
    it "returns all photos" do
      get "/api/v1/photos", headers: { "Authorization" => "Bearer my-test-token" }

      expect(response).to have_http_status(:ok)
      expect(response.parsed_body.count).to eq(5)
    end
  end
end

Submitting JSON data

require "rage/rspec"

RSpec.describe Api::V1::PhotosController, type: :request do
  describe "#create" do
    it "creates a photo" do
      post "/api/v1/photos", params: { data: "...", caption: "..." }, as: :json
      expect(response).to have_http_status(:created)
    end

    it "returns newly created photo" do
      post "/api/v1/photos", params: { data: "...", caption: "..." }, as: :json
      expect(response.parsed_body["data"]).to be_present
    end
  end
end

Testing subdomain constrained requests

require "rage/rspec"

Rage.routes.draw do
  namespace "api/v1" do
    resources :photos, constraints: { subdomain: "api" }
  end
end

RSpec.describe Api::V1::PhotosController, type: :request do
  before { host! "api.example.com" }

  it "returns all photos" do
    get "/api/v1/photos"

    expect(response).to have_http_status(:ok)
    expect(response.parsed_body.count).to eq(5)
  end
end

Clone this wiki locally