J'utilise symboles de code d'état HTTP dans le code d'un contrôleur tel que:
render json: {
auth_token: user.authentication_token,
user: user
},
status: :created
ou
render json: {
errors: ["Missing parameter."]
},
success: false,
status: :unprocessable_entity
Dans le code de ma spécification de demande, je voudrais également utiliser les symboles:
post user_session_path, email: @user.email, password: @user.password
expect(last_response.status).to eq(201)
...
expect(last_response.status).to eq(422)
Cependant, chaque test où j'utilise les symboles au lieu d'entiers échoue:
Failure/Error: expect(last_response.status).to eq(:created)
expected: :created
got: 201
(compared using ==)
Voici la dernière liste de symboles de code d'état HTTP dans Rack .
D'une part, la réponse est construite avec des méthodes comme:
succès?
réorienter?
impraticable?
liste complète: response.methods.grep(/\?/)
D'un autre côté, les prédicats Rspec transforment chaque foo?
méthode à un be_foo
matcher.
Je ne suis pas sûr que vous puissiez avoir le 201 de cette façon, malheureusement, mais la création d'un matcher personnalisé est assez facile.
Remarque Rails test uniquement comptez sur quelques statuts .
L'objet response
répond à plusieurs types de symboles sous forme de messages. Vous pouvez donc simplement faire:
expect(response).to be_success
expect(response).to be_error
expect(response).to be_missing
expect(response).to be_redirect
Pour les autres types, tels que :created
, vous pouvez créer un matcher personnalisé simple pour cela qui enveloppe assert_response
:
RSpec::Matchers.define :have_status do |type, message = nil|
match do |_response|
assert_response type, message
end
end
expect(response).to have_status(:created)
expect(response).to have_status(404)
Cela devrait fonctionner correctement pour les spécifications du contrôleur qui ont la configuration d'état appropriée. Cela ne fonctionnera pas pour les spécifications des fonctionnalités. Je n'ai pas essayé avec les spécifications de la demande, donc votre kilométrage peut y varier.
La raison pour laquelle cela fonctionne est qu'il exploite le fait que les spécifications du contrôleur RSpec ont une configuration d'état similaire dans les coulisses. Donc quand assert_response
accède @response
c'est disponible.
Ce matcher peut probablement être amélioré en copiant simplement le code utilisé par assert_response
dans le match:
RSpec::Matchers.define :have_status do |type, message = nil|
match do |response|
if Symbol === type
if [:success, :missing, :redirect, :error].include?(type)
response.send("#{type}?")
else
code = Rack::Utils::SYMBOL_TO_STATUS_CODE[type]
response.response_code == code
end
else
response.response_code == type
end
end
failure_message do |response|
message or
"Expected response to be a <#{type}>, but was <#{response.response_code}>"
end
end
Ceci est maintenant disponible dès la sortie de l'emballage avec RSpec Rails 3: https://www.relishapp.com/rspec/rspec-Rails/v/3-0/docs/ matchers/have-http-status-matcher
cela fonctionne pour moi:
expect(response.response_code).to eq(Rack::Utils::SYMBOL_TO_STATUS_CODE[:not_found])
Avec rspec-Rails (à partir de rspec 3) il est possible d'utiliser
expect(response).to have_http_status(:created)
Mise à jour 2018-06-11:
À partir de Rails 6, certains des matchers seront remplacés (par ex. success
par successful
).