This blog is part of our Rails 5 series.

Before Rails 5, while sending requests with integration test setup, we needed to add format option to send request with different Mime type.

class ProductsControllerTest < ActionController::TestCase
  def test_create

    post :create, { product: { name: 'Rails 5 book' } }.to_json,
        format: :json,
        headers: { 'Content-Type' => 'application/json' }

    assert_equal 'application/json', request.content_type
    assert_equal({ id: 1, name: 'Rails 5 book' }, JSON.parse(response.body))
  end
end

This format for writing tests with JSON type is lengthy and needs too much information to be passed to request as well.

Improvement with Rails 5

In Rails 5, we can provide Mime type while sending request by passing it with as option and all the other information like headers and format will be passed automatically.

class ProductsControllerTest < ActionDispatch::IntegrationTest
  def test_create
    post products_url, params: { product: { name: 'Rails 5 book' } }, as: :json

    assert_equal 'application/json', request.content_type
    assert_equal({ 'id' => 1, 'name' => 'Rails 5 book' }, response.parsed_body)
  end
end

As we can notice, we don’t need to parse JSON anymore.

With changes in this PR, we can fetch parsed response without needing to call JSON.parse at all.

Custom Mime Type

We can also register our own encoders for any registered Mime Type.

class ProductsControllerTest < ActionDispatch::IntegrationTest

  def setup
    Mime::Type.register 'text/custom', :custom

    ActionDispatch::IntegrationTest.register_encoder :custom,
      param_encoder: -> params { params.to_custom },
      response_parser: -> body { body }

  end

  def test_index
    get products_url, params: { name: 'Rails 5 book' }, as: :custom

    assert_response :success
    assert_equal 'text/custom', request.content_type
  end
end