Testing Your API

Testing is a critical part of building robust APIs. Since Grape applications are Rack-based, you can test them using tools like rack-test.

Testing with Rack-Test

rack-test provides a simple DSL for making requests to a Rack application and inspecting the response.

RSpec Example

Here’s how you can test a Grape API with RSpec and rack-test.

# spec/api/twitter_api_spec.rb
require 'spec_helper'

describe Twitter::API do
  include Rack::Test::Methods

  def app
    Twitter::API
  end

  context 'GET /api/statuses/public_timeline' do
    it 'returns an empty array of statuses' do
      get '/api/statuses/public_timeline'
      expect(last_response.status).to eq(200)
      expect(JSON.parse(last_response.body)).to eq []
    end
  end

  context 'GET /api/statuses/:id' do
    it 'returns a status by id' do
      status = Status.create!
      get "/api/statuses/#{status.id}"
      expect(last_response.body).to eq status.to_json
    end
  end
end

Minitest Example

# test/api/twitter_api_test.rb
require 'test_helper'

class TwitterAPITest < Minitest::Test
  include Rack::Test::Methods

  def app
    Twitter::API
  end

  def test_public_timeline_returns_empty_array
    get '/api/statuses/public_timeline'
    assert last_response.ok?
    assert_equal [], JSON.parse(last_response.body)
  end
end

Testing with Rails

If your Grape API is mounted within a Rails application, you can use Rails's built-in testing tools.

RSpec with Rails

When using RSpec in a Rails project, request specs are the ideal place to test your API.

# spec/requests/twitter_api_spec.rb
require 'rails_helper'

describe Twitter::API, type: :request do
  context 'GET /api/statuses/public_timeline' do
    it 'returns an empty array of statuses' do
      get '/api/statuses/public_timeline'
      expect(response.status).to eq(200)
      expect(JSON.parse(response.body)).to eq []
    end
  end
end

Stubbing Helpers

Testing endpoints that rely on helper methods (like current_user) can be tricky. Grape provides the Grape::Endpoint.before_each hook to allow stubbing these methods before each request.

describe 'an endpoint that needs helpers stubbed' do
  include Rack::Test::Methods

  def app
    MyAPI
  end

  before do
    Grape::Endpoint.before_each do |endpoint|
      # Allow the endpoint instance to receive the helper call
      allow(endpoint).to receive(:current_user).and_return(double('user'))
    end
  end

  after do
    # Important: clean up the hook after the test
    Grape::Endpoint.before_each nil
  end

  it 'stubs the helper and returns a successful response' do
    get '/protected_resource'
    expect(last_response.status).to eq(200)
  end
end