rails matchers ruby-on-rails rspec http-status-codes human-readable

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])