如何在使用rescue_from时使用Rails4和RSpec测试渲染状态:404

我有一个带有’PagesController’的Rails4应用程序。

当找不到页面时,show-method抛出一个自定义的exception’PageNotFoundError’。

在控制器的顶部,我rescue_from PageNotFoundError, with: :render_not_found定义了rescue_from PageNotFoundError, with: :render_not_found

render not foundPagesController的私有方法, PagesController所示:

 def render_not_found flash[:alert]=t(:page_does_not_exists, title: params[:id]) @pages = Page.all render :index, status: :not_found #404 end 

rails-log in development-mode显示:

 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) 

所以,到目前为止,它接缝我的:status =>:not_found有效。

当我做curl -v http://0.0.0.0:3000/pages/readmefcurl日志

 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 

但是RSpec的以下测试失败了:

  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 

一切看起来都很好,甚至test.log说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) 

我尝试了不同的服务器,WebRICK,瘦,独角兽。 在开发和生产模式中,一切都按预期工作。 即使test.log也是正确的,但测试失败了。

谁能告诉我为什么测试说200而不是404?

RSpec 3+的另一种方法是测试exception:

 it 'respond with 404 if page not found' do expect{ get :show, :id => 'bad_id' }.to raise_error(ActionController::RoutingError) end 

虽然我对这个解决方案不是很满意,但至少这是一个解决方法:

我把测试分成了两个不同的规格。 一个用于测试响应代码404(使用GET而不是访问),另一个用于测试警报。 第二个测试是必要的,因为get不会呈现视图 – 即使render_views是在spec文件的顶部定义的。

  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 

这里的问题是你混淆了Capybarafunction测试和RSpec控制器测试。 visit是由Capybara提供的方法,并且RS /控制器测试提供/ response您不能一起使用它们

要将此测试作为单个RSpec控制器测试,您可以执行以下操作:

 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 get line与你发布的不一样 – 我没有包含controller参数,就好像你把它放在spec/controllers/pages_controller_spec.rb里,你不需要它)

或者作为单个Capybarafunction测试:

 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 
Interesting Posts