简体   繁体   中英

Why is ruby rails to_json returning string instead of hash?

I am following a tutorial of building a JSON api using ruby version 2.3.1 and rails version 5.0.7. The tutorial is located at https://scotch.io/tutorials/build-a-restful-json-api-with-rails-5-part-two When running RSpec tests, I get:

Failures:

1) AuthenticationController POST /auth/login when request is valid returns an authentication token Failure/Error: before { post 'auth/login', params: valid_credentials, headers: headers }

 NoMethodError:
   undefined method `symbolize_keys' for "{\"email\":\"foo@bar.com\",\"password\":\"foobar\"}":String
 # ./spec/controllers/authentication_controller_spec.rb:32:in `block (4 levels) in <top (required)>'
 # ./spec/rails_helper.rb:85:in `block (3 levels) in <top (required)>'
 # ./spec/rails_helper.rb:84:in `block (2 levels) in <top (required)>'

2) AuthenticationController POST /auth/login When request is invalid returns a failure message Failure/Error: before { post '/auth/login', params: invalid_credentials, headers: headers }

 NoMethodError:
   undefined method `symbolize_keys' for #<String:0x007fcb133e88f8>
 # ./spec/controllers/authentication_controller_spec.rb:41:in `block (4 levels) in <top (required)>'
 # ./spec/rails_helper.rb:85:in `block (3 levels) in <top (required)>'
 # ./spec/rails_helper.rb:84:in `block (2 levels) in <top (required)>'

The AuthenticationControllerSpec to which it refers to is as follows:

    require 'rails_helper'
    RSpec.describe AuthenticationController, type: :controller do
      # Authentication test suite
      describe 'POST /auth/login' do
        # create test user
        let!(:user) { create(:user) }

        # set headers for authorization
        let(:headers) { valid_headers.except('Authorization')  }

        # set test valid and invalid credentials
        let(:valid_credentials) do
           { 
              email: user.email, 
              password: user.password 
           }.to_json 
        end # let(:valid_credentials) do 

        let(:invalid_credentials) do 
          {
             email: Faker::Internet.email,
             password: Faker::Internet.password
          }.to_json
        end # let(:invalid_credentials) do 

        # set request.headers to our custom headers
        # before { allow(request).to receive(:headers).and_return(headers) }

        # returns auth token when request is valid
        context 'when request is valid' do
          before { post 'auth/login', params: valid_credentials, headers: headers }

          it 'returns an authentication token' do
            expect(json['auth_token']).not_to be_nil
          end #  it 'returns an authentication token' do
end #     context 'when request is valid' do

        # returns failure message when request is invalid
        context 'When request is invalid' do
          before { post '/auth/login', params: invalid_credentials, headers: headers }

          it 'returns a failure message' do
            expect(json['message']).to match(/Invalid credentials/)
          end # it 'returns a failure message' do
        end # context 'When request is invalid' do


      end # describe 'POST /auth/login' do

    end # RSpec.describe AuthenticationController, type: :controller do

I think the only other relevant file is this module:

    module RequestSpecHelper
      # Parse JSON response to ruby hash
      def json
        JSON.parse(response.body)
      end
    end

Thanks for any and all assistance.

Don't manually convert the params to JSON. RSpec does it automatically for you and expects a hash of parameters and not a string.

let(:valid_credentials) do
  { 
    email: user.email, 
    password: user.password 
  }
end

let(:invalid_credentials) do 
  {
    email: Faker::Internet.email,
    password: Faker::Internet.password
  }
end

Additionally for a new project I would skip controller tests and go straight for request specs which are more future proof .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM