10

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

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

规范/请求/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

很奇怪!!

谢谢

4

4 回答 4

20

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

post '...', {...}.to_json, {'CONTENT_TYPE' => "application/json", 'ACCEPT' => 'application/json'}
于 2013-08-20T15:16:54.043 回答
0

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

data: [
  {
   details: {
    param1: 1
   }**,**
  },
  {
   details: {
    param2: 1
   }
  }
 ]
于 2013-08-20T23:11:16.047 回答
0

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

Rails JSON API 使用 JSON 中的 PARAMS 测试 POST 请求

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

于 2013-09-08T11:58:29.843 回答
0

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

红宝石 2.3.2

导轨(5.0.0.1)

rspec-rails (3.5.2)

在网上搜索问题时,我在https://github.com/rails/rails/issues/26069发现了一个相关问题,它建议的解决方案是在控制器测试中使用它们时将as: :json选项传递给post, etc 方法(有关更多详细信息,请参阅评论https://github.com/rails/rails/issues/26069#issuecomment-240916233get中引用的 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"} ] }

这是错误的。

数据-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"} ] }

这是正确的。

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

还有一件事:在评论中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

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

最后,我在下面分享对我有用的东西

规范/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是使请求参数以预期结构接收的缺失。

于 2021-12-15T12:02:17.323 回答