【问题标题】:RSpec request test merges hashes in array in POST JSON paramsRSpec 请求测试在 POST JSON 参数中合并数组中的哈希
【发布时间】:2013-08-22 15:43:34
【问题描述】:

看起来像 RSpec 中的一个错误,但也许我遗漏了一些东西。

我有一个请求规范,我在其中发布了一个包含哈希数组的 JSON:

spec/requests/dummy_request_spec.rb:

post "http://my.server.com/some/route", {
  format: :json,
  data: [
    {
      details: {
        param1: 1
      },
    },
    {
      details: {
        param2: 1
      }
    }
  ]
}

出于某种奇怪的原因,RSpec 将散列合并为一个元素,然后将它们发送到服务器。 打印出控制器收到的参数:

data: [
  {
    details: {
      param1: 1,
      param2: 2
    },
  },
]

版本: rspec-2.13.0 rails-3.2.10

很奇怪!!

谢谢

【问题讨论】:

    标签: ruby-on-rails json rspec request params


    【解决方案1】:

    我在使用以下版本时遇到了问题帖子中报告的相同问题

    红宝石 2.3.2

    导轨 (5.0.0.1)

    rspec-rails (3.5.2)

    在网络上搜索问题我在https://github.com/rails/rails/issues/26069 发现了一个相关问题,它建议的解决方案是在控制器测试中使用post、get 等方法时将as: :json 选项传递给它们(有关更多详细信息,请参阅评论 https://github.com/rails/rails/issues/26069#issuecomment-240916233 中引用的 PR)。使用该解决方案并没有解决我遇到的参数混合问题。以下是我在推荐解决方案中使用的不同类型数据的结果:

    在我的控制器规范中,我有以下内容

    before(:each) do
     request.accept = "application/json"
    end
    

    在测试日志中我确实看到请求正在被处理

    Processing by Api::V1::MyController#my_action as JSON
    

    数据-1

    data = [
      {
        param_1: "param_1_value",
      },
      {
        param_2: "param_2_value",
      }
    ]
    
    params.merge!(my_data: data)
    
    post :my_action, params: params, as: :json
    

    请求参数如下所示

    { "my_data"=> [ {"param_1"=>"param_1_value", "param_2"=>"param_2_value"} ] }
    

    这是错误。

    数据-2

    data = [
      {
        param_1: "param_1_value",
        something_else: ""
      },
      {
        param_2: "param_2_value",
        another_thing: ""
      }
    ]
    
    params.merge!(my_data: data)
    
    post :my_action, params: params, as: :json
    

    请求参数如下所示

    { "my_data"=> [ {"param_1"=>"param_1_value", "something_else"=>"", "another_thing"=>"", "param_2"=>"param_2_value"} ] }
    

    这是错误。

    Data-3

    data = [
      {
        param_1: "param_1_value",
        param_2: ""
      },
      {
        param_1: ""
        param_2: "param_2_value",
      }
    ]
    
    params.merge!(my_data: data)
    
    post :my_action, params: params, as: :json
    

    请求参数如下所示

    { "my_data"=>[ {"param_1"=>"param_1_value", "param_2"=>""}, {"param_1"=>"", "param_2"=>"param_2_value"} ] }
    

    这是正确。

    应该注意的是,对于没有 as: :json 选项的 Data-3,我在请求参数中也收到了正确的数据。

    还有一件事:在评论https://github.com/rails/rails/issues/26069#issuecomment-240358290 中建议处理上述问题的替代解决方案如下

    另一个解决方法是将嵌套属性指定为不是数组,而是指定为 哈希:

    params = {
          id: @book.id,
          book: {
            title: 'Cool',
            pages_params: {
              "0" => { id: @page.id, content: 'another content' },
              "1" => { id: @delete_page.id, _destroy: 1 },
              "2" => { content: 'another new page' }
            }
          },
          format: :json
        }
    

    不幸的是,这已从嵌套的文档中删除 属性,所以我不知道这是否会保持有效。 http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

    但是这个解决方案有一个缺点是我们需要手动清理控制器端的数据以使其恢复到预期的结构,即哈希数组。

    最后,我将在下面分享对我有用的方法

    spec/shared_contexts.rb

    RSpec.shared_context "common helpers" do
    
      def set_request_header(request_obj:, request_header_name:, request_header_value:)
        request_obj.headers[request_header_name] = request_header_value
      end
    
      def set_request_header_content_type_as_json(request_obj:)
        set_request_header(request_obj: request_obj, request_header_name: 'CONTENT_TYPE', request_header_value: 'application/json')
      end
    end
    

    然后在我的规范文件中

    require 'shared_contexts'
    
    RSpec.describe Api::V1::MyController, :type => :controller do
      include_context "common helpers"
    
      context "POST #my_action" do  
        it "my example" do
          data = [
            {
              param_1: "param_1_value",
            },
            {
              param_2: "param_2_value",
            }
          ]
    
          params.merge!(my_data: data)
    
          set_request_header_content_type_as_json(request_obj: request)
    
          post :my_action, params: params
        end
      end 
    end
    

    可以看出,设置请求标头 CONTENT_TYPE 是缺少使请求参数以预期结构接收的内容。

    【讨论】:

      【解决方案2】:

      知道了!表单数据不支持哈希数组
      RSpec 默认将其发布为表单数据。解决方案:

      post '...', {...}.to_json, {'CONTENT_TYPE' => "application/json", 'ACCEPT' => 'application/json'}
      

      【讨论】:

      • 旁注:支持表单数据的哈希数组,但需要“索引”字段,否则实体将合并为一个。如果您想发送文件数组,这可能很有用。
      【解决方案3】:

      您的回答帮助我回答了我自己的帖子:

      Rails JSON API testing POST request with PARAMS in JSON

      您应该接受它是正确的:) 感谢您的帮助

      【讨论】:

        【解决方案4】:

        另外,请注意您有一个额外的逗号:

        data: [
          {
           details: {
            param1: 1
           }**,**
          },
          {
           details: {
            param2: 1
           }
          }
         ]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-04-29
          • 1970-01-01
          • 1970-01-01
          • 2020-07-24
          • 1970-01-01
          • 2018-07-29
          • 2013-08-22
          相关资源
          最近更新 更多