Ruby-on-rails 将 Rspec 默认 GET 请求格式设置为 JSON
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11022839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Set Rspec default GET request format to JSON
提问by Drazen Mokic
I am doing functional tests for my controllers with Rspec. I have set my default response format in my router to JSON, so every request without a suffix will return JSON.
我正在使用 Rspec 对我的控制器进行功能测试。我已将路由器中的默认响应格式设置为 JSON,因此每个没有后缀的请求都将返回 JSON。
Now in rspec, i get an error (406) when i try
现在在 rspec 中,当我尝试时出现错误 (406)
get :index
I need to do
我需要去做
get :index, :format => :json
Now because i am primarily supporting JSON with my API, it is very redundant having to specify the JSON format for every request.
现在因为我的 API 主要支持 JSON,所以必须为每个请求指定 JSON 格式是非常多余的。
Can i somehow set it to default for all my GET requests? (or all requests)
我可以以某种方式将它设置为我所有 GET 请求的默认值吗?(或所有请求)
回答by Pratik Khadloya
before :each do
request.env["HTTP_ACCEPT"] = 'application/json'
end
回答by knoopx
Put this in spec/support:
把这个放在spec/support:
require 'active_support/concern'
module DefaultParams
extend ActiveSupport::Concern
def process_with_default_params(action, parameters, session, flash, method)
process_without_default_params(action, default_params.merge(parameters || {}), session, flash, method)
end
included do
let(:default_params) { {} }
alias_method_chain :process, :default_params
end
end
RSpec.configure do |config|
config.include(DefaultParams, :type => :controller)
end
And then simply override default_params:
然后简单地覆盖default_params:
describe FooController do
let(:default_params) { {format: :json} }
...
end
回答by schmijos
The following works for me with rspec 3:
以下适用于rspec 3:
before :each do
request.headers["accept"] = 'application/json'
end
This sets HTTP_ACCEPT.
这一套HTTP_ACCEPT。
回答by Franklin Yu
Here is a solution that
这是一个解决方案
- works for request specs,
- works with Rails 5, and
- does not involve private API of Rails (like
process).
- 适用于请求规格,
- 适用于 Rails 5,并且
- 不涉及 Rails 的私有 API(如
process)。
Here's the RSpec configuration:
这是 RSpec 配置:
module DefaultFormat
extend ActiveSupport::Concern
included do
let(:default_format) { 'application/json' }
prepend RequestHelpersCustomized
end
module RequestHelpersCustomized
l = lambda do |path, **kwarg|
kwarg[:headers] = {accept: default_format}.merge(kwarg[:headers] || {})
super(path, **kwarg)
end
%w(get post patch put delete).each do |method|
define_method(method, l)
end
end
end
RSpec.configure do |config|
config.include DefaultFormat, type: :request
end
Verified with
验证与
describe 'the response format', type: :request do
it 'can be overridden in request' do
get some_path, headers: {accept: 'text/plain'}
expect(response.content_type).to eq('text/plain')
end
context 'with default format set as HTML' do
let(:default_format) { 'text/html' }
it 'is HTML in the context' do
get some_path
expect(response.content_type).to eq('text/html')
end
end
end
FWIW, The RSpec configuration can be placed:
FWIW,可以放置RSpec配置:
Directly in
spec/spec_helper.rb. This is not suggested; the file will be loaded even when testing library methods inlib/.Directly in
spec/rails_helper.rb.(my favorite) In
spec/support/default_format.rb, and be loaded explicitly inspec/rails_helper.rbwithrequire 'support/default_format'In
spec/support, and be loaded byDir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }which loads all the files in
spec/support.
直接在
spec/spec_helper.rb. 不建议这样做;即使在lib/.直接在
spec/rails_helper.rb.(我的最爱)在
spec/support/default_format.rb和明确加载spec/rails_helper.rb与require 'support/default_format'在
spec/support,并被加载Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }它将所有文件加载到
spec/support.
This solution is inspired by knoopx's answer. His solution doesn't work for request specs, and alias_method_chainhas been deprecated in favor of Module#prepend.
此解决方案的灵感来自Knoopx 的回答。他的解决方案不适用于请求规范,并且alias_method_chain已被弃用而支持Module#prepend.
回答by Dan Kohn
In RSpec 3, you need make JSON tests be request specs in order to have the views render. Here is what I use:
在 RSpec 3 中,您需要使 JSON 测试成为请求规范才能呈现视图。这是我使用的:
# spec/requests/companies_spec.rb
require 'rails_helper'
RSpec.describe "Companies", :type => :request do
let(:valid_session) { {} }
describe "JSON" do
it "serves multiple companies as JSON" do
FactoryGirl.create_list(:company, 3)
get 'companies', { :format => :json }, valid_session
expect(response.status).to be(200)
expect(JSON.parse(response.body).length).to eq(3)
end
it "serves JSON with correct name field" do
company = FactoryGirl.create(:company, name: "Jane Doe")
get 'companies/' + company.to_param, { :format => :json }, valid_session
expect(response.status).to be(200)
expect(JSON.parse(response.body)['name']).to eq("Jane Doe")
end
end
end
As for setting the format on all tests, I like the approach from this other answer: https://stackoverflow.com/a/14623960/1935918
至于在所有测试中设置格式,我喜欢其他答案中的方法:https: //stackoverflow.com/a/14623960/1935918
回答by zw963
Perhaps you could add the first answer into spec/spec_helper or spec/rails_helper with this:
也许您可以将第一个答案添加到 spec/spec_helper 或 spec/rails_helper 中:
config.before(:each) do
request.env["HTTP_ACCEPT"] = 'application/json' if defined? request
end
if in model test (or any not exist request methods context), this code just ignore. it worked with rspec 3.1.7 and rails 4.1.0 it should be worked with all rails 4 version generally speaking.
如果在模型测试(或任何不存在的请求方法上下文)中,则此代码将忽略。它适用于 rspec 3.1.7 和 rails 4.1.0,一般来说应该适用于所有 rails 4 版本。
回答by settheline
Running Rails 5 and Rspec 3.5 I had to set the headers to accomplish this.
运行 Rails 5 和 Rspec 3.5 我必须设置标题才能完成此操作。
post '/users', {'body' => 'params'}, {'ACCEPT' => 'application/json'}
Thi matches what the example in the docslooks like:
这与文档中的示例相匹配:
require "rails_helper"
RSpec.describe "Widget management", :type => :request do
it "creates a Widget" do
headers = {
"ACCEPT" => "application/json", # This is what Rails 4 accepts
"HTTP_ACCEPT" => "application/json" # This is what Rails 3 accepts
}
post "/widgets", { :widget => {:name => "My Widget"} }, headers
expect(response.content_type).to eq("application/json")
expect(response).to have_http_status(:created)
end
end
回答by mpospelov
For those folks who work with request tests the easiest way I found is to override #processmethod in ActionDispatch::Integration::Sessionand set default asparameter to :jsonlike this:
对于那些使用请求测试的人,我发现最简单的方法是覆盖#process方法ActionDispatch::Integration::Session并将默认as参数设置为:json这样:
module DefaultAsForProcess
def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: :json)
super
end
end
ActionDispatch::Integration::Session.prepend(DefaultAsForProcess)
回答by DBrown
Per the Rspec docs, the supported method is through the headers:
根据Rspec docs,支持的方法是通过标题:
require "rails_helper"
RSpec.describe "Widget management", :type => :request do
it "creates a Widget" do
headers = {
"ACCEPT" => "application/json", # This is what Rails 4 and 5 accepts
"HTTP_ACCEPT" => "application/json", # This is what Rails 3 accepts
}
post "/widgets", :params => { :widget => {:name => "My Widget"} }, :headers => headers
expect(response.content_type).to eq("application/json")
expect(response).to have_http_status(:created)
end
end
回答by Kenneth Cheng
为什么 RSpec 的方法“get”、“post”、“put”、“delete”在 gem(或 Rails 之外)的控制器规范中不起作用?
Based off this question, you could try redefining process() in ActionController::TestCase from https://github.com/rails/rails/blob/32395899d7c97f69b508b7d7f9b7711f28586679/actionpack/lib/action_controller/test_case.rb.
基于这个问题,您可以尝试从https://github.com/rails/rails/blob/32395899d7c97f69b508b7d7f9b7711f28586679/actionpack/lib/action_controller/test_case.rb重新定义 ActionController::TestCase 中的 process() 。
Here is my workaround though.
不过,这是我的解决方法。
describe FooController do
let(:defaults) { {format: :json} }
context 'GET index' do
let(:params) { defaults }
before :each do
get :index, params
end
# ...
end
context 'POST create' do
let(:params) { defaults.merge({ name: 'bar' }) }
before :each do
post :create, params
end
# ...
end
end

