RSpec 请求规范 post 一个空数组
RSpec request spec post an empty array
我目前正在 rails 中开发一个 API 端点。如果我需要的数据无效,我想确保端点响应具有正确的错误状态。我需要一个 id 数组。无效值之一是空数组。
有效
{ vendor_district_ids: [2, 4, 5, 6]}
无效
{ vendor_district_ids: []}
请求规格 RSpec
所以我想要一个请求规范来控制我的行为。
require 'rails_helper'
RSpec.describe Api::PossibleAppointmentCountsController, type: :request do
let(:api_auth_headers) do
{ 'Authorization' => 'Bearer this_is_a_test' }
end
describe 'POST /api/possible_appointments/counts' do
subject(:post_request) do
post api_my_controller_path,
params: { vendor_district_ids: [] },
headers: api_auth_headers
end
before { post_request }
it { expect(response.status).to eq 400 }
end
end
如您所见,我在 subject
块内的参数中使用了一个空数组。
控制器内的值
在我的控制器中,我正在使用
获取数据
params.require(:vendor_district_ids)
值如下
<ActionController::Parameters {"vendor_district_ids"=>[""], "controller"=>"api/my_controller", "action"=>"create"} permitted: false>
vendor_district_ids
的值是一个空字符串数组。当我用 postman
制作 post 时,我没有相同的值。
值 post人
如果我post
{ "vendor_district_ids": [] }
控制器将收到
<ActionController::Parameters {"vendor_district_ids"=>[], "controller"=>"api/my_controller", "action"=>"create"} permitted: false>
这里是空数组。
问题
我是不是在请求规范中做错了什么,或者这是 RSpec
的错误?
其实是rack-test >= 0.7.0
[1]造成的。
它将空数组转换为 param[]=
,后者随后被解码为 ['']
。
如果您尝试 运行 使用相同的代码,例如rack-test 0.6.3
您会看到 vendor_district_ids
根本没有添加到查询中:
# rack-test 0.6.3
Rack::Test::Utils.build_nested_query('a' => [])
# => ""
# rack-test >= 0.7.0
Rack::Test::Utils.build_nested_query('a' => [])
# => "a[]="
Rack::Utils.parse_nested_query('a[]=')
# => {"a"=>[""]}
[1] https://github.com/rack-test/rack-test/commit/ece681de8ffee9d0caff30e9b93f882cc58f14cb
找到答案了!
问题
问题是在 Rack 的 query_parser
中发现的,而不是像前面的答案所指出的那样实际上是在 rack-test 中。
"paramName[]="
到 {"paramName":[""]}
的实际翻译发生在 Rack 的 query_parser。
问题举例:
post '/posts', { ids: [] }
{"ids"=>[""]} # By default, Rack::Test will use HTTP form encoding, as per docs: https://github.com/rack/rack-test/blob/master/README.md#examples
解决方案
将您的参数转换为 JSON,方法是使用 'require 'json'
将 JSON gem 要求到您的应用程序中,并使用 .to_json
附加您的参数散列。
并在您的 RSPEC 请求中指定此请求的 content-type 是 JSON。
修改上面例子的例子:
post '/posts', { ids: [] }.to_json, { "CONTENT_TYPE" => "application/json" }
{"ids"=>[]} # explicitly sending JSON will work nicely
对于所有想知道的人 — 有一个快捷的解决方案:
post '/posts', params: { ids: [] }, as: :json
我目前正在 rails 中开发一个 API 端点。如果我需要的数据无效,我想确保端点响应具有正确的错误状态。我需要一个 id 数组。无效值之一是空数组。
有效
{ vendor_district_ids: [2, 4, 5, 6]}
无效
{ vendor_district_ids: []}
请求规格 RSpec
所以我想要一个请求规范来控制我的行为。
require 'rails_helper'
RSpec.describe Api::PossibleAppointmentCountsController, type: :request do
let(:api_auth_headers) do
{ 'Authorization' => 'Bearer this_is_a_test' }
end
describe 'POST /api/possible_appointments/counts' do
subject(:post_request) do
post api_my_controller_path,
params: { vendor_district_ids: [] },
headers: api_auth_headers
end
before { post_request }
it { expect(response.status).to eq 400 }
end
end
如您所见,我在 subject
块内的参数中使用了一个空数组。
控制器内的值
在我的控制器中,我正在使用
获取数据params.require(:vendor_district_ids)
值如下
<ActionController::Parameters {"vendor_district_ids"=>[""], "controller"=>"api/my_controller", "action"=>"create"} permitted: false>
vendor_district_ids
的值是一个空字符串数组。当我用 postman
制作 post 时,我没有相同的值。
值 post人
如果我post
{ "vendor_district_ids": [] }
控制器将收到
<ActionController::Parameters {"vendor_district_ids"=>[], "controller"=>"api/my_controller", "action"=>"create"} permitted: false>
这里是空数组。
问题
我是不是在请求规范中做错了什么,或者这是 RSpec
的错误?
其实是rack-test >= 0.7.0
[1]造成的。
它将空数组转换为 param[]=
,后者随后被解码为 ['']
。
如果您尝试 运行 使用相同的代码,例如rack-test 0.6.3
您会看到 vendor_district_ids
根本没有添加到查询中:
# rack-test 0.6.3
Rack::Test::Utils.build_nested_query('a' => [])
# => ""
# rack-test >= 0.7.0
Rack::Test::Utils.build_nested_query('a' => [])
# => "a[]="
Rack::Utils.parse_nested_query('a[]=')
# => {"a"=>[""]}
[1] https://github.com/rack-test/rack-test/commit/ece681de8ffee9d0caff30e9b93f882cc58f14cb
找到答案了!
问题
问题是在 Rack 的 query_parser
中发现的,而不是像前面的答案所指出的那样实际上是在 rack-test 中。
"paramName[]="
到 {"paramName":[""]}
的实际翻译发生在 Rack 的 query_parser。
问题举例:
post '/posts', { ids: [] }
{"ids"=>[""]} # By default, Rack::Test will use HTTP form encoding, as per docs: https://github.com/rack/rack-test/blob/master/README.md#examples
解决方案
将您的参数转换为 JSON,方法是使用 'require 'json'
将 JSON gem 要求到您的应用程序中,并使用 .to_json
附加您的参数散列。
并在您的 RSPEC 请求中指定此请求的 content-type 是 JSON。
修改上面例子的例子:
post '/posts', { ids: [] }.to_json, { "CONTENT_TYPE" => "application/json" }
{"ids"=>[]} # explicitly sending JSON will work nicely
对于所有想知道的人 — 有一个快捷的解决方案:
post '/posts', params: { ids: [] }, as: :json