21

「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-log には次のように表示されます。

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、Thin、Unicorn を試しました。開発モードと本番モードでは、すべてが期待どおりに機能します。test.log も正しいですが、テストは失敗します。

テストで 404 ではなく 200 と表示される理由を誰か教えてもらえますか?

4

3 に答える 3

18

RSpec 3+ を使用した別のアプローチは、例外をテストすることです。

it 'responds with a 404 if the page is not found' do
  expect { get(:show, id: 'bad_id') }.to raise_error(ActionController::RoutingError)
end
于 2014-12-11T10:52:44.607 に答える
14

私はこの解決策にあまり満足していませんが、少なくともこれは回避策です:

テストを 2 つの個別の仕様に分割しました。1 つは応答コード 404 (visit の代わりに 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
于 2013-08-04T20:01:31.263 に答える
9

ここでの問題は、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

(Nb get行はあなたが投稿したものとは異なります-controllerこれを所属する場所に置くかのように、paramを含めてspec/controllers/pages_controller_spec.rbいません。それは必要ありません)

または、単一の Capybara 機能テストとして:

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
于 2014-08-24T06:41:31.560 に答える