unitarias rails pruebas elaborando crear con apis ruby-on-rails rspec functional-testing

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

  1. funciona para las especificaciones de solicitud,
  2. funciona con Rails 5, y
  3. 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:

  1. Directamente en spec/spec_helper.rb . Esto no es sugerido; el archivo se cargará incluso cuando se prueben métodos de biblioteca en lib/ .

  2. Directamente en spec/rails_helper.rb .

  3. (mi favorito) En spec/support/default_format.rb , y se carga explícitamente en spec/rails_helper.rb con

    require ''support/default_format''

  4. En spec/support , y ser cargado por

    Dir[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


¿Por qué los métodos de RSpec, "get", "post", "put", "delete" no funcionan en una especificación de controlador en una gema (o fuera de Rails)?

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