DEV Community

loading...

Don't forget `as: :json` when testing JSON API

uiur profile image zato ・1 min read

When you write tests for your JSON API with request spec, typical code is like:

describe 'POST /restaurants' do
  let(:params) { { name: 'pizza foobar' } }

  it 'creates a restaurant' do
    post '/restaurants', headers: headers, params: params
    expect(response).to have_http_status(:created)
    expect(response.parsed_body).to match(
      'id' => String,
      'name' => 'pizza foobar'
    )
  end
end
Enter fullscreen mode Exit fullscreen mode

But this doesn't test the API right, technically.

Because this test sends a POST request with application/x-www-form-urlencoded, not application/json.

Mostly, you expect request body with application/json for JSON API. This code does not simulate requests properly.

So, use as: :json option:

post '/restaurants', headers: headers, params: params, as: :json
Enter fullscreen mode Exit fullscreen mode

I'm lazy enough to avoid passing as: :json every time.

Usually I override those helpers to pass as: :json option by default:

module RequestHelper
  %i[get post patch put delete].each do |method_name|
    define_method(method_name) do |path, args = {}|
      default_options = { as: :json }
      process method_name, path, default_options.merge(args)
    end
  end
end

RSpec.configure do |config|
  config.include RequestHelper, type: :request
  # ...
Enter fullscreen mode Exit fullscreen mode

Discussion

pic
Editor guide