Set Rspec default GET request format to JSON

前端 未结 10 1902
失恋的感觉
失恋的感觉 2020-12-02 22:31

I am doing functional tests for my controllers with Rspec. I have set my default response format in my router to JSON, so every request without a suffix will return JSON.

10条回答
  •  自闭症患者
    2020-12-02 23:10

    Here is a solution that

    1. works for request specs,
    2. works with Rails 5, and
    3. does not involve private API of Rails (like process).

    Here's the RSpec configuration:

    module DefaultFormat
      extend ActiveSupport::Concern
    
      included do
        let(:default_format) { 'application/json' }
        prepend RequestHelpersCustomized
      end
    
      module RequestHelpersCustomized
        l = lambda do |path, **kwarg|
          kwarg[:headers] = {accept: default_format}.merge(kwarg[:headers] || {})
          super(path, **kwarg)
        end
        %w(get post patch put delete).each do |method|
          define_method(method, l)
        end
      end
    end
    
    RSpec.configure do |config|
      config.include DefaultFormat, type: :request
    end
    

    Verified with

    describe 'the response format', type: :request do
      it 'can be overridden in request' do
        get some_path, headers: {accept: 'text/plain'}
        expect(response.content_type).to eq('text/plain')
      end
    
      context 'with default format set as HTML' do
        let(:default_format) { 'text/html' }
    
        it 'is HTML in the context' do
          get some_path
          expect(response.content_type).to eq('text/html')
        end
      end
    end
    

    FWIW, The RSpec configuration can be placed:

    1. Directly in spec/spec_helper.rb. This is not suggested; the file will be loaded even when testing library methods in lib/.

    2. Directly in spec/rails_helper.rb.

    3. (my favorite) In spec/support/default_format.rb, and be loaded explicitly in spec/rails_helper.rb with

      require 'support/default_format'
      
    4. In spec/support, and be loaded by

      Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
      

      which loads all the files in spec/support.

    This solution is inspired by knoopx's answer. His solution doesn't work for request specs, and alias_method_chain has been deprecated in favor of Module#prepend.

提交回复
热议问题