RailsのWebサービス開発をテストする際、Controllerをログイン状態別にテストしたいシーンが多々あります。
この場合の、もっともプリミティブなテスト設計は以下のようなものになると考えています。
- ログイン判定のコードをスタブする
- ログイン時、未ログイン時のHTTPステータスコードを判定する
ログイン判定のコードをスタブする
Railsのscaffoldでspec/controllersディレクトリに生成されるvalid_session
にスタブを実装すると、フィール on rail になります。
# This should return the minimal set of values that should be in the session
# in order to pass any filters (e.g. authentication) defined in
# InquiriesController. Be sure to keep this updated too.
let(:valid_session) {
allow(controller).to receive_message_chain(:login?).and_return(true)
}
この例ではlogin?
というログイン判定処理をスタブしており「trueを返すとログイン状態である」という実装の想定です。
このスタブを利用して、ログイン状態別のテストケースを作ります。
ログイン時、未ログイン時のHTTPステータスコードを判定する
valid_sessionにスタブを実装することで、個別のテストケースから利用できます。
以下のように、HTTPリクエストメソッド(get, postなど)のオプションにvalid_sessionキーワードを付けるor付けない別に宣言的にログイン状態に応じた処理を定義できます。
describe "GET #index" do
it "HTTP302レスポンスとともにログイン処理にリダイレクト" do
get :index, {}
expect(response.status).to eq(302)
end
it "HTTP200で処理成功" do
get :index, {}, valid_session
expect(response.status).to eq(200)
end
end
また、ログイン状態別のアクセス制御についてはこの例のように戻り値の HTTPステータスコードを活用できます。
この例では、未ログイン時にはログイン画面にredirect_to
でリダイレクトする実装の想定で、redirect_to
にともなうステータス”302 Found”をテストしています。
ログイン時には一般的にステータス”200 OK”を返すはずなので、eq(200)
を検証しています。
ログイン状態の処理につき、より高レベルなケースを実装したい場合は、単にvalid_sessionつきでリクエストする任意のケースを追加していくだけです。
今回の例では、セキュリティ面のアクセス制御の妥当性とリクエストフローの処理がひと通り完結している(たとえば500エラーが起きていない)ことを検証できます。
Chuma Takahiro