【问题标题】:Why is ruby rails to_json returning string instead of hash?为什么 ruby​​ rails to_json 返回字符串而不是哈希?
【发布时间】:2018-10-17 16:32:05
【问题描述】:

我正在学习使用 ruby​​ 版本 2.3.1 和 rails 版本 5.0.7 构建 JSON api 的教程。教程位于https://scotch.io/tutorials/build-a-restful-json-api-with-rails-5-part-two 运行 RSpec 测试时,我得到:

失败:

1) AuthenticationController POST /auth/login 当请求有效时返回一个身份验证令牌 失败/错误:在 { post 'auth/login' 之前,参数:valid_credentials,标头:标头}

 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 请求无效时返回失败信息 失败/错误:在 { post '/auth/login' 之前,参数:invalid_credentials,标题:标题 }

 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)>'

它所指的AuthenticationControllerSpec如下:

    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

我认为唯一的其他相关文件是这个模块:

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

感谢您的所有帮助。

【问题讨论】:

  • 因为to_json 返回的是字符串,而不是哈希?请参阅docs

标签: ruby-on-rails json ruby rspec


【解决方案1】:

不要手动将参数转换为 JSON。 RSpec 会自动为您执行此操作,并且需要参数哈希而不是字符串。

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

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

另外,对于一个新项目,我会跳过控制器测试和go straight for request specs which are more future proof

【讨论】:

    猜你喜欢
    • 2021-11-19
    • 2014-06-19
    • 2020-04-05
    • 1970-01-01
    • 2021-10-01
    • 2013-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多