Set Rspec default GET request format to JSON

前端 未结 10 1834
失恋的感觉
失恋的感觉 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 22:58

    Put this in spec/support:

    require 'active_support/concern'
    
    module DefaultParams
      extend ActiveSupport::Concern
    
      def process_with_default_params(action, parameters, session, flash, method)
        process_without_default_params(action, default_params.merge(parameters || {}), session, flash, method)
      end
    
      included do
        let(:default_params) { {} }
        alias_method_chain :process, :default_params
      end
    end
    
    RSpec.configure do |config|
      config.include(DefaultParams, :type => :controller)
    end
    

    And then simply override default_params:

    describe FooController do
        let(:default_params) { {format: :json} }
        ...
    end
    
    0 讨论(0)
  • 2020-12-02 23:01

    In RSpec 3, you need make JSON tests be request specs in order to have the views render. Here is what I use:

    # spec/requests/companies_spec.rb
    require 'rails_helper'
    
    RSpec.describe "Companies", :type => :request do
      let(:valid_session) { {} }
    
      describe "JSON" do
        it "serves multiple companies as JSON" do
          FactoryGirl.create_list(:company, 3)
          get 'companies', { :format => :json }, valid_session
          expect(response.status).to be(200)
          expect(JSON.parse(response.body).length).to eq(3) 
        end
    
        it "serves JSON with correct name field" do
          company = FactoryGirl.create(:company, name: "Jane Doe")
          get 'companies/' + company.to_param, { :format => :json }, valid_session
          expect(response.status).to be(200)
          expect(JSON.parse(response.body)['name']).to eq("Jane Doe")
        end
      end
    end
    

    As for setting the format on all tests, I like the approach from this other answer: https://stackoverflow.com/a/14623960/1935918

    0 讨论(0)
  • 2020-12-02 23:06

    For those folks who work with request tests the easiest way I found is to override #process method in ActionDispatch::Integration::Session and set default as parameter to :json like this:

    module DefaultAsForProcess
      def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: :json)
        super
      end
    end
    
    ActionDispatch::Integration::Session.prepend(DefaultAsForProcess)
    
    0 讨论(0)
  • 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.

    0 讨论(0)
提交回复
热议问题