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