RSpec 请求测试在 POST JSON 参数中合并数组中的哈希

Posted

技术标签:

【中文标题】RSpec 请求测试在 POST JSON 参数中合并数组中的哈希【英文标题】:RSpec request test merges hashes in array in POST JSON params 【发布时间】: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

很奇怪!!

谢谢

【问题讨论】:

【参考方案1】:

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

红宝石 2.3.2

导轨 (5.0.0.1)

rspec-rails (3.5.2)

在网络上搜索问题我在https://github.com/rails/rails/issues/26069 发现了一个相关问题,它建议的解决方案是在控制器测试中使用postget 等方法时将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
   
  
 ]

【讨论】:

以上是关于RSpec 请求测试在 POST JSON 参数中合并数组中的哈希的主要内容,如果未能解决你的问题,请参考以下文章

Rspec 控制器测试,传递 JSON 参数

测试在RSpec中重定向的请求

如何测试Controller post:使用rspec在rails上创建JSON api?

如何为需要用户身份验证的API构建Rspec请求测试

Rspec如何创建一个方法来“干燥”请求的一些参数?

postman测试post请求参数为json类型