Railsのチュートリアルをやっていて、7章でIntegration testがうまくpassできませんでした。
その時のまとめです。
環境
- iMac El capitan 10.11.6
- vagrant centos 6.7 minimal
- ruby 2.3.1p112
- rails 4.2.6
Passできなかったのは、
- リスト7.21: 無効なユーザー登録に対するテスト
です。
大体以下のようなエラーが出ていました。
expecting <"users/new"> but rendering with
<["rescues/_source", "rescues/_trace", "rescues/_request_and_response",
"rescues/diagnostics", "rescues/layout", "_markup", "_inner_console_markup.html",
"layouts/inlined_string", "_prompt_box_markup.html", "style.css", "console",
"layouts/javascript", "main", "error_page", "index"]>
Expected response to be a <success>, but was <422>
原因
原因は、Integration testの実行環境がdevelopmentだったため、RailsのCSRFの保護機能によって、外部からのPOSTがブロックされていたためでした。
テストの実行環境が test だったら特に問題にならなかったと思います。
ただ、Railsのチュートリアルをやっている段階では、多くの人は developmentでやっているのではないかと思うので、同じようにつまづいてしまう人のために書いておこうと思います。
解決策
解決策は至って単純で、実行環境のRailsのCSRF保護機能をオフにしてあげれば良いです。
もちろん、production環境ではオフにできませんが、開発環境、それもチュートリアル中であればこの対策で十分だと思います。
Railsのdevelopment環境のconfigに、以下を追記します。
# Disable request forgery protection in development environment.
config.action_controller.allow_forgery_protection = false
ちなみに、実際のCSRF保護の呼び出しは、application_controller.rbで行われています。
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end
protect_from_forgery でCSRF保護機能を呼び出しています。
解決策として、もしくは、実行環境をtestに変更する、というのでも良いのかもしれません。
デフォルトURL
上記を調べていて気づいたことですが、railsのintegration testで users_url などの_urlヘルパーを使う場合は、デフォルトのURLがサンプルのURLになっているので気をつけましょう。
こちらを変更する場合も、configファイルに追記することで、URLを変更することができます。
これ以外にも、リクエスト送信先のホストを変更する手段は幾つかあるようですが、全体を変更する場合は、設定ファイルが妥当だと思います。
開発環境のconfigに以下を追記します。
config.action_controller.default_url_options = { host: '192.168.33.10' }
IPの部分はご自分の環境に合わせてください。