13

我正在使用rails-api gem 来构建 Web 服务,并希望使用 RSpec 测试我的 API。无论 HTTP 方法如何,我发出的每个请求都将CONTENT_TYPE标头设置为“application/x-www-form-urlencoded”。在我尝试在控制器中使用wrap_parameters并且它对 params 哈希没有任何影响之前,这并不是真正的问题:

class ApplicationController < ActionController::API
  include ActionController::ParamsWrapper
end

class ProjectsController < ApplicationController
  wrap_parameters :project, include: [:name]
  # ...
end

这个 hack不再有效(@request 为零),我发现的其他 Stack Overflow 帖子也没有工作。

如果我在我的 RSpec 测试中提出以下请求:

put "/projects/1.json", {name: 'Updated Project 1'}

并在我的控制器中放置一个调试器,我得到:

(rdb:1) p params
    { "name"=>"Updated Project 1",
  "action"=>"update",
  "controller"=>"projects",
  "id"=>"5539bbd9-010c-4cfb-88d3-82dadbc99507",
  "format"=>"json"
}

(rdb:1) p request.content_type
"application/x-www-form-urlencoded"

我期待在 params 哈希中看到类似这样的内容(注意添加了项目密钥):

{ "name"=>"Updated Project 1",
  "action"=>"update",
  "controller"=>"projects",
  "id"=>"5539bbd9-010c-4cfb-88d3-82dadbc99507",
  "format"=>"json",
  "project" => {"name" => "Updated Project 1"}
}

是否可以仅使用 RSpec 设置内容类型标头?还是我必须为此功能使用机架/测试?

4

7 回答 7

22

很多挫折和变化,这对我有用。 导轨 3.2.12 Rspec 2.10

 @request.env["HTTP_ACCEPT"] = "application/json"
 @request.env["CONTENT_TYPE"] = "application/json"
 put :update, :id => 1, "email" => "bing@test.com"

wrap_parameters 似乎正在以这种方式声明

wrap_parameters User, format: :json

用于User模型

于 2013-03-26T01:48:56.473 回答
7

This worked for me Rails 4.0.3 and Rspec 2.14.1 if anyone is looking for more recent versions.

put '/projects/1.json', {name: 'Updated Project 1'}, {
  'HTTP_ACCEPT' => 'application/json',
  'CONTENT_TYPE' => 'application/json'
}

and

wrap_parameters Project, format: :json
于 2014-12-22T20:06:45.180 回答
5

使用新的 Rails v5.0.x API only 设置,我发现 Rails 将所有内容默认为的这个"application/x-www-form-urlencoded"问题对于使用 RSpec-Rails 请求进行测试仍然存在问题

这是我为解决问题所做的工作:

在以下位置创建支持文件./spec/support/json_requests.rb

将其编辑为类似这样以覆盖所有仅 API JSON 请求的行为:

module JsonRequests
  def get(*args)
    super(*json_args(*args))
  end

  def post(*args)
    super(*json_args(*args))
  end

  def update(*args)
    super(*json_args(*args))
  end

  def patch(*args)
    super(*json_args(*args))
  end

  def put(*args)
    super(*json_args(*args))
  end

  def delete(*args)
    super(*json_args(*args))
  end

  def json_args(path, params = {}, headers = {})
    [path, params.to_json, headers.merge('CONTENT_TYPE' => 'application/json')]
  end
end

RSpec.configure do |config|
  config.include JsonRequests, type: :request
end

请记住,这将覆盖其中的所有规范,./spec/requests因此如果您需要使用"application/x-www-form-urlencoded",您也可以include根据需要在Describe 'something' do块中手动使用此模块。

于 2016-02-09T22:23:23.510 回答
4

Rails 5没有黑客:

put(:update,
    params: {project_id: 1},
    body: {name: 'Updated Project 1'}.to_json,
    as: :json)

这设置content_type正确。在控制器params中将同时保存参数和正文。

于 2019-04-02T15:37:22.580 回答
2

它的 2021 年,Rails 6.1,我不得不用它as: :json来修复参数中哈希数组的这种奇怪的修改。

put(:update, params: the_params_hash, as: :json)
于 2021-03-23T04:09:27.133 回答
0

如果您使用的是 Rails 4(和 rspec ~3.7)并且不想使用内联语法:

request.headers["CONTENT_TYPE"] = "application/json"
于 2018-01-16T19:08:11.117 回答
0

导轨 5

headers = { 'CONTENT_TYPE' => 'application/json' }
params = { user_type: 'tester' } 

在那个请求之后

post '/api/v1/users/test', params.to_json, headers

.to_json从请求路线中删除

于 2020-12-25T09:05:14.110 回答