问题
I have a Rails4 application with a 'PagesController'.
The show-method throws a customized Exception 'PageNotFoundError' when a Page is not found.
On top of the controller I defined
rescue_from PageNotFoundError, with: :render_not_found
render not found
is a private method of PagesController
and looks like:
def render_not_found
flash[:alert]=t(:page_does_not_exists, title: params[:id])
@pages = Page.all
render :index, status: :not_found #404
end
The rails-log in development-mode shows:
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)
So, it seams my :status => :not_found works, so far.
When I do 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
But the following test with RSpec fails:
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
Everything looks fine and even the test.log says 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)
I tried different Servers, WebRICK, Thin, unicorn. Everything works as expected in development and production mode. Even the test.log is correct but the test fails.
Can anybody tell me why the test says 200 instead of 404?
回答1:
Another approach with RSpec 3+ would be to test for an exception:
it 'respond with 404 if page not found' do
expect{ get :show, :id => 'bad_id' }.to raise_error(ActionController::RoutingError)
end
回答2:
Although I'm not very happy with this solution, at least this is a work around:
I splited the test into two separate specs. One for testing the response code 404 (with GET instead of visit) and a second to test the alert. The second test is necessary because get
doesn't render the view - even if render_views
is defined on top of the spec-file.
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
回答3:
The problem here is that you are confusing Capybara feature tests and RSpec controller tests. visit
is a method provided by Capybara and get
/ response
are provided by RSpec controller tests - you can't use them together.
To test this as a single RSpec controller test you can do:
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
(N.b. The get line is different from what you posted - I haven't included the controller
param as if you put this in spec/controllers/pages_controller_spec.rb
where it belongs you don't need that)
Or as a single Capybara feature test:
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
来源:https://stackoverflow.com/questions/18026598/how-to-test-render-status-404-with-rails4-and-rspec-when-using-rescue-from