我在使用以下版本时遇到了问题帖子中报告的相同问题
红宝石 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 是缺少使请求参数以预期结构接收的内容。