Specific mime types in controller tests in Rails 5

Abhishek Jain

By Abhishek Jain

on July 5, 2016

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.

1
2class ProductsControllerTest < ActionController::TestCase
3  def test_create
4
5    post :create, { product: { name: 'Rails 5 book' } }.to_json,
6        format: :json,
7        headers: { 'Content-Type' => 'application/json' }
8
9    assert_equal 'application/json', request.content_type
10    assert_equal({ id: 1, name: 'Rails 5 book' }, JSON.parse(response.body))
11  end
12end
13

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.

1
2class ProductsControllerTest < ActionDispatch::IntegrationTest
3  def test_create
4    post products_url, params: { product: { name: 'Rails 5 book' } }, as: :json
5
6    assert_equal 'application/json', request.content_type
7    assert_equal({ 'id' => 1, 'name' => 'Rails 5 book' }, response.parsed_body)
8  end
9end
10

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.

1
2class ProductsControllerTest < ActionDispatch::IntegrationTest
3
4  def setup
5    Mime::Type.register 'text/custom', :custom
6
7    ActionDispatch::IntegrationTest.register_encoder :custom,
8      param_encoder: -> params { params.to_custom },
9      response_parser: -> body { body }
10
11  end
12
13  def test_index
14    get products_url, params: { name: 'Rails 5 book' }, as: :custom
15
16    assert_response :success
17    assert_equal 'text/custom', request.content_type
18  end
19end
20