How to check for a JSON response using RSpec?

后端 未结 14 1315
谎友^
谎友^ 2020-11-29 16:03

I have the following code in my controller:

format.json { render :json => { 
        :flashcard  => @flashcard,
        :lesson     => @lesson,
             


        
14条回答
  •  余生分开走
    2020-11-29 16:32

    A lot of the above answers are a bit out of date, so this is a quick summary for a more recent version of RSpec (3.8+). This solution raises no warnings from rubocop-rspec and is inline with rspec best practices:

    A successful JSON response is identified by two things:

    1. The content type of the response is application/json
    2. The body of the response can be parsed without errors

    Assuming that the response object is the anonymous subject of the test, both of the above conditions can be validate using Rspec's built in matchers:

    context 'when response is received' do
      subject { response }
    
      # check for a successful JSON response
      it { is_expected.to have_attributes(content_type: include('application/json')) }
      it { is_expected.to have_attributes(body: satisfy { |v| JSON.parse(v) }) }
    
      # validates OP's condition
      it { is_expected.to satisfy { |v| JSON.parse(v.body).key?('success') }
      it { is_expected.to satisfy { |v| JSON.parse(v.body)['success'] == true }
    end
    

    If you're prepared to name your subject then the above tests can be simplified further:

    context 'when response is received' do
      subject(:response) { response }
    
      it 'responds with a valid content type' do
        expect(response.content_type).to include('application/json')
      end
    
      it 'responds with a valid json object' do
        expect { JSON.parse(response.body) }.not_to raise_error
      end
    
      it 'validates OPs condition' do
        expect(JSON.parse(response.body, symoblize_names: true))
          .to include(success: true)
      end
    end
    

提交回复
热议问题