「PagesController」を備えたRails4アプリケーションがあります。
ページが見つからない場合、show-methodはカスタマイズされた例外「PageNotFoundError」をスローします。
コントローラーの上にrescue_from PageNotFoundError, with: :render_not_found
を定義しました
render not found
は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ログは以下を示します:
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/readmef
curlログを実行すると
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、Thin、Unicornを試しました。すべては、開発モードとプロダクションモードで期待どおりに機能します。 test.logも正しいですが、テストは失敗します。
テストで404ではなく200と表示される理由を誰かに教えてもらえますか?
私はこのソリューションにあまり満足していませんが、少なくともこれは回避策です。
テストを2つの個別の仕様に分割しました。 1つは応答コード404(訪問ではなくGETを使用)をテストするためのもので、もう1つはアラートをテストするためのものです。 get
はビューをレンダリングしないため、2番目のテストが必要です。たとえrender_views
がスペックファイルの上に定義されていてもです。
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
RSpec 3+の別のアプローチは、例外をテストすることです。
it 'respond with 404 if page not found' do
expect{ get :show, :id => 'bad_id' }.to raise_error(ActionController::RoutingError)
end
ここでの問題は、Capybara機能テストとRSpecコントローラーテストを混同していることです。 visit
はCapybaraによって提供されるメソッドであり、get
/response
はRSpecコントローラーテストによって提供されます-それらを一緒に使用することはできません。
これを単一の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
(N.b. get行はあなたが投稿したものとは異なります-controller
パラメータを含めていないので、これをspec/controllers/pages_controller_spec.rb
に入れたかのように、必要ありません)
または、単一のカピバラ機能テストとして:
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