7

リクエスト仕様の途中で、すべての例外が rspec にバブルアップするのを単純に許可する方法を知りたいです。

例がこれを明確にすることを願っています。次の要求仕様と対応するアプリケーション コードがあるとします。

# user_browses_posts_spec.rb
feature 'User views a post' do
  scenario 'this should fail with route missing' do
    FactoryGirl.create(:post)
    visit(root_path)
    click_on('View Post')
  end
end

# config/routes.rb
MyApp::Application.routes.draw do
  root to: 'posts#index'
  # notice I have not defined a :posts resource, so post_path should raise NoMethodError
end

# assume a totally standard app/controllers/posts_controller.rb

# app/views/posts/index.html.erb
<% @posts.each do |post| %>
  <%= link_to 'View Post', post_path(post) %>  # this line should fail
<% end %>

テストを実行すると、次のように表示されます。

Failure/Error: click_on('View Post')
Capybara::ElementNotFound:
  no link or button 'View Post' found

これは、アプリ内から NoMethodError が発生したときに、スペック ランナーが通常の Rails 開発エラー ページ (エラー メッセージ、バックトレース、パラメーターなどを含む) を見たため、問題を認識しなかったためです。

しかし、端末で見たいのは次のとおりです。

Failure/Error: visit(root_path)
NoMethodError:
  undefined method `post_path' for #<PostsController:0x007fea60a779c8>

私の質問は、レールのエラー処理を完全に無効にして、NoMethodError が rspec までバブルするようにするにはどうすればよいかということです。

ありがとう!

4

2 に答える 2

2

私はこれが可能だとは思わない。ただし、visit()は機能テストを目的としているため、visit()でコントローラーエラーが発生する可能性があるとしても、実際には発生させたくないと思います。

リクエストの仕様は独自のコンテキストで実行されます。つまり、visit()メソッドは、コントローラーメソッドを直接呼び出すのではなく、ブラウザーであるかのようにURLにアクセスします。したがって、リクエストはすべてのRackミドルウェアとRailsルーティングレイヤーを通過します。そこでのエラー処理は、現実の世界と同じように動作します。これは、このような「機能」テストに適しています。

このようなものを手動でテストするとどうなるか考えてみてください。特定の(壊れた)URLにアクセスすると、ブラウザに何が表示されますか?2つのうちの1つ:

  • 本番環境では、通常、静的エラーページです。
  • 開発中、エラーを説明するテキストを含む生成されたページ(スタックトレース付き)

どちらの場合も、実際にはブラウザはHTMLページを受け取ります。

次に、このページを見て、「ねえ、それは私が期待していたページではありません!」と自分に言い聞かせます。この時点で、がうまくいかなかったかを判断しました。ページが期待したものではありません。次に、ログを調査するか、開発モードのエラーページでスタックトレースを読み取って、これがうまくいかなかった理由を特定する必要があります。

仕様は基本的に同じことをしていますが、自動化されています。visit()呼び出しは問題なく機能し、ある種のHTMLページを生成しまし。次に、テストはリンクをクリックして、特定のコンテンツが含まれていることを検証しようとしますが、ここでテストは失敗します。この手順は、概念的には「Hey!」と言っているのと同じです。ページが読み込まれ、期待した内容が含まれていない場合にのみ。

必要に応じて、コントローラーメソッドを直接単体テストできます。それらは、はるかに詳細なレベルで何がうまくいかなかったかを教えてくれます。

機能テスト:

  • 内容:ページに期待されるコンテンツが含まれていませんでした
  • 理由:コントローラーアクションがエラーをスローしました

単体テスト:

  • :コントローラーアクションがエラーをスローしました
  • 理由:誰かがそのファイルをプロジェクト(または何でも)に入れるのを忘れた
于 2012-08-22T22:07:21.120 に答える
0

あなたはこれを行うことができます:

expect { visit(root_path) }.to raise_exception

特定の例外を指定することもできます。https://www.relishapp.com/rspec/rspec-expectations/v/2-12/docs/built-in-matchers/raise-error-matcherを参照してください。

于 2012-12-02T23:03:07.403 に答える