ruby on rails - matchers - ¿Cómo utilizar los símbolos de código de estado HTTP en RSpec?
rspec rails 5 (4)
Con rspec-rails (a partir de rspec 3) es posible utilizar
expect(response).to have_http_status(:created)
Actualización 2018-06-11 :
A partir de Rails 6, algunos de los competidores serán reemplazados (por ejemplo, success
por successful
).
Utilizo los símbolos de código de estado HTTP en el código de un controlador como:
render json: {
auth_token: user.authentication_token,
user: user
},
status: :created
o
render json: {
errors: ["Missing parameter."]
},
success: false,
status: :unprocessable_entity
En el código de mi especificación de solicitud también me gustaría usar los símbolos:
post user_session_path, email: @user.email, password: @user.password
expect(last_response.status).to eq(201)
...
expect(last_response.status).to eq(422)
Sin embargo, cada prueba donde uso los símbolos en lugar de los enteros falla:
Failure/Error: expect(last_response.status).to eq(:created)
expected: :created
got: 201
(compared using ==)
Aquí está la lista más reciente de símbolos de código de estado HTTP en Rack .
El objeto de response
responde a varios de los tipos de símbolos como mensajes. Así que simplemente puedes hacer:
expect(response).to be_success
expect(response).to be_error
expect(response).to be_missing
expect(response).to be_redirect
Para los otros tipos, tales como :created
, puede crear un emparejador personalizado simple para esto que ajusta 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)
Esto debería funcionar bien para las especificaciones del controlador que tienen la configuración de estado adecuada. No funcionará para las especificaciones de características. No he intentado con especificaciones de solicitud, por lo que su kilometraje puede variar allí.
La razón por la que esto funciona es que aprovecha el hecho de que las especificaciones del controlador RSpec tienen una configuración de estado similar tras bambalinas. Entonces, cuando assert_response
accede a @response
está disponible.
Este emparejador probablemente se puede mejorar simplemente copiando el código utilizado por assert_response
en el emparejador:
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
ACTUALIZACIÓN: 2014-07-02
Ahora está disponible de manera inmediata con RSpec Rails 3: https://www.relishapp.com/rspec/rspec-rails/v/3-0/docs/matchers/have-http-status-matcher
Por un lado, la respuesta se construye con métodos como:
¿éxito?
redirigir?
improcedente
lista completa do:
response.methods.grep(//?/)
Por otro lado, los predicados de Rspec transforman cada foo?
Método para un be_foo
matcher.
Lamentablemente, no estoy seguro de que puedas tener el 201 de esta manera, pero crear un emparejador personalizado es bastante fácil.
Nota La prueba de Rails solo se basa en algunos estados .
esto funciona para mi
expect(response.response_code).to eq(Rack::Utils::SYMBOL_TO_STATUS_CODE[:not_found])