RSpec请求规范发布一个空数组

时间:2018-07-18 07:36:22

标签: ruby-on-rails ruby rspec http-post rspec-rails

我目前正在开发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发表信息时没有相同的值。

邮递员的价值

如果我发布

{ "vendor_district_ids": [] }

控制器将收到

<ActionController::Parameters {"vendor_district_ids"=>[], "controller"=>"api/my_controller", "action"=>"create"} permitted: false>

这是空的数组。

问题

我在请求规范中做错了什么吗?还是来自RSpec的错误?

3 个答案:

答案 0 :(得分:1)

这实际上是由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

答案 1 :(得分:0)

看起来像是一种奇怪的行为,但是我认为将参数转换为json应该会有所帮助:

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: [] }.to_json,
        headers: api_auth_headers
    end

    before { post_request }

    it { expect(response.status).to eq 400 }
  end
end

答案 2 :(得分:0)

找到答案!

问题

问题是在机架的query_parser内部发现的,而不是先前的答案所示的机架测试内部。

"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

解决方案

通过使用'require 'json'要求将JSON gem插入应用程序,并使用.to_json附加参数散列,将参数转换为JSON。

并在您的RSPEC请求中指定此请求的内容类型为JSON。

通过修改上面的示例得到一个示例:

post '/posts', { ids: [] }.to_json, { "CONTENT_TYPE" => "application/json" }
{"ids"=>[]} # explicitly sending JSON will work nicely