Définir Rspec par défaut obtenir le format de requête à JSON
je fais des tests fonctionnels pour mes contrôleurs avec Rspec. J'ai défini mon format de réponse par défaut dans mon routeur à JSON, ainsi chaque requête sans suffixe retournera JSON.
maintenant dans rspec, je reçois une erreur (406) quand j'essaie
get :index
j'ai besoin de faire
get :index, :format => :json
maintenant parce que je supporte principalement JSON avec mon API, il est très redondant d'avoir à spécifier le format JSON pour chaque requête.
est-ce que je peux le définir par défaut pour toutes mes requêtes GET? (ou toutes les demandes)
9 réponses
before :each do
request.env["HTTP_ACCEPT"] = 'application/json'
end
mettez ceci dans 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
et ensuite simplement remplacer default_params
:
describe FooController do
let(:default_params) { {format: :json} }
...
end
les travaux suivants pour moi avec rspec 3 :
before :each do
request.headers["accept"] = 'application/json'
end
cet ensemble HTTP_ACCEPT
.
dans RSpec 3, vous avez besoin de faire des tests JSON être Request specs afin que les vues soient rendues. Voici ce que j'utilise:
# 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
pour ce qui est de définir le format sur tous les tests, j'aime l'approche de cette autre réponse: https://stackoverflow.com/a/14623960/1935918
Voici une solution qui
- fonctionne pour les specs de requête,
- travaille avec des Rails 5, et
- n'implique pas D'API privée de Rails (comme
process
).
Voici la 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
vérifié avec
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 configuration RSpec peut être placée:
-
directement dans
spec/spec_helper.rb
. Ceci n'est pas suggéré; le fichier sera chargé même si l'on teste les méthodes de la bibliothèque danslib/
. -
directement dans
spec/rails_helper.rb
. -
(mon préféré) dans
spec/support/default_format.rb
, et être chargé explicitement dansspec/rails_helper.rb
avecrequire 'support/default_format'
-
dans
spec/support
, et être chargé parDir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
qui charge tous les fichiers de
spec/support
.
cette solution est inspirée de knoopx's answer . Sa solution ne fonctionne pas pour les spécifications de demande, et alias_method_chain
a été déprécié en faveur de Module#prepend
.
peut-être pourriez-vous ajouter la première réponse dans spec/spec_helper ou spec/rails_helper avec ceci:
config.before(:each) do
request.env["HTTP_ACCEPT"] = 'application/json' if defined? request
end
si dans le contexte de l'essai sur modèle (ou de toute méthode de requête inexistante), ce code ne tient pas compte. il a travaillé avec rspec 3.1.7 et rails 4.1.0 il doit être travaillé avec tous les rails 4 version Généralement parlant.
Running Rails 5 et Rspec 3.5 J'ai dû régler les en-têtes pour accomplir ceci.
post '/users', {'body' => 'params'}, {'ACCEPT' => 'application/json'}
cela correspond à ce que l'exemple dans le docs ressemble à:
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
pour les gens qui travaillent avec des tests de requêtes la façon la plus facile que j'ai trouvée est de surcharger #process
méthode dans ActionDispatch::Integration::Session
et définir le paramètre par défaut as
à :json
comme ceci:
module DefaultAsForProcess
def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: :json)
super
end
end
ActionDispatch::Integration::Session.prepend(DefaultAsForProcess)
basé sur cette question, vous pouvez essayer de redéfinir le processus () dans ActionController::TestCase de https://github.com/rails/rails/blob/32395899d7c97f69b508b7d7f9b7711f28586679/actionpack/lib/action_controller/test_case.rb .
voici ma solution.
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