ruby on rails - Cómo probar el estado de renderizado: 404 con Rails4 y RSpec cuando se usa rescue_from
ruby-on-rails http-response-codes (3)
Tengo una aplicación Rails4 con un ''PagesController''.
El método show muestra una excepción personalizada ''PageNotFoundError'' cuando no se encuentra una página.
En la parte superior del controlador rescue_from PageNotFoundError, with: :render_not_found
render not found
es un método privado de PagesController
y se parece a:
def render_not_found
flash[:alert]=t(:page_does_not_exists, title: params[:id])
@pages = Page.all
render :index, status: :not_found #404
end
El registro de rieles en modo de desarrollo muestra:
Started GET "/pages/readmef" for 127.0.0.1 at 2013-08-02 23:11:35 +0200
Processing by PagesController#show as HTML
Parameters: {"id"=>"readmef"}
..
Completed 404 Not Found in 14ms (Views: 12.0ms)
Por lo tanto, combina mi: status =>: not_found funciona, hasta ahora.
Cuando hago curl -v http://0.0.0.0:3000/pages/readmef
curl logs
curl -v http://localhost:3000/pages/readmef
* About to connect() to localhost port 3000 (#0)
* Trying 127.0.0.1...
* connected
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /pages/readmef HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8x zlib/1.2.5
> Host: localhost:3000
> Accept: */*
>
< HTTP/1.1 404 Not Found
< X-Frame-Options: SAMEORIGIN
Pero la siguiente prueba con RSpec falla:
it ''renders an error if page not found'' do
visit page_path(''not_existing_page_321'')
expect(response.status).to eq(404)
within( ''.alert-error'' ) do
page.should have_content(''Page not_existing_page_321 doesn/'t exist'')
end
end
1) PagesController renders an error if page not found
Failure/Error: expect(response.status).to eq(404)
expected: 404
got: 200
Todo se ve bien e incluso el test.log dice 404
$ tail -f log/test.log
Started GET "/pages/not_existing_page_321" for 127.0.0.1 at 2013-08-03 09:48:13 +0200
Processing by PagesController#show as HTML
Parameters: {"id"=>"not_existing_page_321"}
Rendered pages/_page.haml (0.8ms)
Rendered layouts/_navigation.haml (0.6ms)
Rendered layouts/_messages.haml (0.2ms)
Rendered layouts/_locales.haml (0.3ms)
Rendered layouts/_footer.haml (0.6ms)
Completed 404 Not Found in 6ms (Views: 4.5ms)
Probé diferentes servidores, WebRICK, Thin, unicorn. Todo funciona como se espera en el modo de desarrollo y producción. Incluso el test.log es correcto pero la prueba falla.
¿Alguien puede decirme por qué la prueba dice 200 en lugar de 404?
Aunque no estoy muy contento con esta solución, al menos esta es una solución:
Dividí la prueba en dos especificaciones separadas. Uno para probar el código de respuesta 404 (con GET en lugar de la visita) y otro para probar la alerta. La segunda prueba es necesaria porque get
no render_views
la vista, incluso si render_views
se define encima del archivo de especificaciones.
it ''response with 404 if page not found'' do
get :show, { controller: ''pages'', id: ''not_existing_page_321'' }
expect(response.status).to eq(404)
end
it ''renders an error-message if page not found and shows index'' do
visit page_path(''page_not_found'')
within ''.alert-error'' do
page.should have_content("Page page_not_found doesn''t exist")
end
end
El problema aquí es que usted está confundiendo las pruebas de características de Capybara y las pruebas del controlador RSpec. visit
es un método proporcionado por Capybara y get
/ response
se proporciona mediante las pruebas del controlador RSpec, no se pueden usar juntos .
Para probar esto como una sola prueba de controlador RSpec puede hacer:
it "returns a not found response" do
get :show, { id: ''not_existing_page_321'' }
expect(response.status).to eq(404)
expect(response.text).to match(/Page page_not_found doesn''t exist/)
end
(Nb. La línea de obtención es diferente de la que usted publicó. No he incluido el parámetro del controller
como si colocara esto en spec/controllers/pages_controller_spec.rb
donde no corresponde, no necesita eso)
O como una prueba única de Capibara:
it "renders a not found response" do
visit page_path(''page_not_found'')
expect(page.status_code).to eq(404)
within ''.alert-error'' do
expect(page).to have_content("Page page_not_found doesn''t exist")
end
end
Otro enfoque con RSpec 3+ sería probar una excepción:
it ''respond with 404 if page not found'' do
expect{ get :show, :id => ''bad_id'' }.to raise_error(ActionController::RoutingError)
end