ruby on rails - rails - Establezca el formato de solicitud GET predeterminado de Rspec en JSON
rails web service json (9)
Aquí hay una solución que
- funciona para las especificaciones de solicitud,
- funciona con Rails 5, y
- no involucra API privada de Rails (como
process
).
Aquí está la configuración de 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
Verificado con
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, la configuración de RSpec se puede colocar:
Directamente en
spec/spec_helper.rb
. Esto no es sugerido; el archivo se cargará incluso cuando se prueben métodos de biblioteca enlib/
.Directamente en
spec/rails_helper.rb
.(mi favorito) En
spec/support/default_format.rb
, y se carga explícitamente enspec/rails_helper.rb
conrequire ''support/default_format''
En
spec/support
, y ser cargado porDir[Rails.root.join(''spec/support/**/*.rb'')].each { |f| require f }
que carga todos los archivos en
spec/support
.
Esta solución está inspirada en la respuesta de Knoopx . Su solución no funciona para las especificaciones de solicitud, y alias_method_chain
ha quedado en desuso en favor de Module#prepend
.
Estoy haciendo pruebas funcionales para mis controladores con Rspec. Establecí mi formato de respuesta predeterminado en mi enrutador en JSON, por lo que cada solicitud sin sufijo devolverá JSON.
Ahora en rspec, obtengo un error (406) cuando intento
get :index
necesito hacer
get :index, :format => :json
Ahora, dado que principalmente apoyo JSON con mi API, es muy redundante tener que especificar el formato JSON para cada solicitud.
¿De alguna manera puedo configurarlo para todas mis solicitudes GET? (o todas las solicitudes)
En RSpec 3, debe hacer que las pruebas JSON sean especificaciones de solicitud para que las vistas se procesen. Esto es lo que uso:
# 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
En cuanto a establecer el formato en todas las pruebas, me gusta el enfoque de esta otra respuesta: https://.com/a/14623960/1935918
Lo siguiente me funciona con rspec 3 :
before :each do
request.headers["accept"] = ''application/json''
end
Esto establece HTTP_ACCEPT
.
Para aquellos que trabajan con pruebas de solicitud, la forma más fácil que encontré es anular el método ActionDispatch::Integration::Session
en ActionDispatch::Integration::Session
y establecer el parámetro predeterminado as
:json
esta manera:
module DefaultAsForProcess
def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: :json)
super
end
end
ActionDispatch::Integration::Session.prepend(DefaultAsForProcess)
Pon esto en 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
Y luego simplemente anula default_params
:
describe FooController do
let(:default_params) { {format: :json} }
...
end
Quizás podría agregar la primera respuesta en spec / spec_helper o spec / rails_helper con esto:
config.before(:each) do
request.env["HTTP_ACCEPT"] = ''application/json'' if defined? request
end
si en la prueba de modelo (o cualquier contexto de métodos de solicitud no existe), este código simplemente ignora. funcionó con rspec 3.1.7 y rieles 4.1.0 debería funcionar con todos los rails 4 versión en general.
Running Rails 5 y Rspec 3.5 tuve que configurar los encabezados para lograr esto.
post ''/users'', {''body'' => ''params''}, {''ACCEPT'' => ''application/json''}
Thi coincide con el aspecto del ejemplo en los 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 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
Basado en esta pregunta, puede intentar redefinir process () en ActionController :: TestCase de https://github.com/rails/rails/blob/32395899d7c97f69b508b7d7f9b7711f28586679/actionpack/lib/action_controller/test_case.rb .
Aquí está mi solución sin embargo.
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
before :each do
request.env["HTTP_ACCEPT"] = ''application/json''
end