2013-08-02 20 views
17

Rails4アプリケーションには 'PagesController'があります。レンダリングステータスのテスト方法:rescue_fromを使用している場合、Rails4とRSpecを使用した場合は

Pageが見つからない場合、show-methodはカスタマイズされたException 'PageNotFoundError'をスローします。

は、コントローラの上に私は rescue_from PageNotFoundError, with: :render_not_found

render not foundPagesControllerのプライベートな方法で定義されており、次のようになります。開発モードでレールがログ

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

を示しています。

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) 

これで、これまでのところmy:status =>:not_foundのような作業が継ぎ目になります。

私はcurl -v http://0.0.0.0:3000/pages/readmefカールログ

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でも正しいですが、テストは失敗します。

404の代わりに200のテストが表示される理由は誰にでも分かりますか?

+1

あなたは 'ページ/ README'、ない'ページ/ readmef'をカール。テストコードは含まれていません。 – sevenseacat

+0

_blushing_ @sevenseacatあなたの権利私はカールコマンドで不足しているfを見ませんでした。実際にカールはうまく動作し、404で反応します。_私は本当に私の眼鏡を使うべきです:/でも仕様はまだ動作しません。私はそれを上に追加しました。 – Nockenfell

+0

@sevenseacatご意見ありがとうございます。それは私を本当の問題に導きます。私は再びその問題を定式化した。 – Nockenfell

答えて

12

私は、このソリューションに非常に満足していないが、少なくともこれは周りの仕事です:

私は2つの別々のスペックにテストをsplited。 1つは応答コード404(訪問の代わりにGET)をテストするためのもので、もう1つはアラートをテストするものです。 getは、render_viewsが仕様ファイルの上に定義されていても、ビューをレンダリングしないため、2番目のテストが必要です。

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 
7

ここでの問題は、あなたがCapybaraの機能テストとRSpecコントローラテストを混同していることです。 visitはCapybaraが提供する方法であり、get/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 

(N.b.:あなたが行うことができ、単一のRSpecのコントローラのテストとしてこれをテストするには

GETラインは、あなたが投稿したものとは異なっている - あなたはそれはあなたがそれを必要としない属しspec/controllers/pages_controller_spec.rbでこれを入れているかのように私は)

または単一カピバラ機能検査としてcontrollerのparamを含めていない。

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 
9

RSpecの3+との別のアプローチは、例外をテストするために、次のようになります。

it 'response with 404 if page not found' do 
    expect{ get :show, :id => 'bad_id' }.to raise_error(ActionController::RoutingError) 
end 
関連する問題