LoginSignup
0
0

More than 3 years have passed since last update.

RSpec入門 5.コントローラスペック

Last updated at Posted at 2020-12-18

前回の続き

RSpecでのコントローラのテストはモデルのテストと統合テストで代替できてしまうため、使う機会は多くありません。
最近では、より高度な統合テストであるシステムスペックが導入されたため、コントローラスペックの出番はさらに減少しました。
とはいえ、既存のプログラムの保守で触れることもあるかと思うので、軽く触れる程度にまとめます。

静的なコントローラのスペック

レスポンスのステータスが成功しているかをテストします。
まずは、スペックファイルの生成。

$ rails g rspec:controller home

spec/controllers/home_controller_spec.rbが生成されます。

コントローラがリクエストに対して正常なレスポンスを返すかテストします。

spec/controllers/home_controller_spec.rb
require 'rails_helper'

RSpec.describe HomeController, type: :controller do
  de
  describe "#index" do
    it "responds successfully" do
      get :index
      expect(response).to be_success
    end
  end
end

responseはブラウザに返すべきアプリケーションの全データを保持しているオブジェクトです。
be_successはレスポンスステータスが成功(200)か、それ以外かをチェックするマッチャです。

特定のHTTPレスポンスコードを確認したいときはhave_http_statusが使えます。

spec/controllers/home_controller_spec.rb
require 'rails_helper'

RSpec.describe HomeController, type: :controller do
  de
  describe "#index" do
    it "responds a 200 response" do
      get :index
      expect(response).to have_http_status "200"
    end
  end
end

認証が必要なコントローラスペック

projectsコントローラのスペックを書いていきます。
このコントローラは、ログイン中のユーザーのみ自分に紐づいたプロジェクトを操作できるという、よくあるCRUDの構造になっています。

$ rails g rspec:controller project

テスト前の準備

先ほどと同じく、まずは成功のレスポンスが返るかテストしますが、認証が必要なコントローラのアクションは事前の準備が必要です。

準備は大きく分けて2つ、
1.Deviseのヘルパーモジュールの読み込み
2.ログイン用のヘルパーメソッドの定義
です。順を追って説明します。

Deviseのヘルパーモジュールの読み込み

Deviseは認証が必要なコントローラのアクションに対して、ユーザーのログイン状態をシミュレートするヘルパーを提供し、テスト実行時はこのヘルパーを使用しています。ですが、RSpecはデフォルトの状態だとこのヘルパーを読み込まないので、使えるように設定を追加します。

spec/rails_helper.rb
  #この1行を追加します
  config.include Devise::Test::ControllerHelpers, type: :controller

この設定で、コントローラスペックでDeviseのヘルパーモジュールが使えるようになります。

ログイン用のヘルパーメソッドの定義

ユーザーがログインしていない状態でリクエストを送ると、ログインページにリダイレクト(302)が返るので、テストのセットアップとしてログインしておく必要があります。

スペック内でログイン処理を記述しても動作はしますが、ログイン処理は頻繁に行うので、今のうちにヘルパーを作っておくのがマストでしょう。

#各々のアプリに合わせたログイン処理
def sign_in(user)
  cookies[:auth_token] = user.auth_token
end

テスト

Projectsコントローラはログインユーザーとゲストユーザーで処理結果が異なるため、複数のテストシナリオを用意します。

spec/controllers/projects_controller_spec.rb
require 'rails_helper'

RSpec.describe ProjectsController, type: :controller do
  de
  describe "#index" do

    context "guest" do
      it "returns a 302 response" do
        get :index
        expect(response).to have_http_status "302"
      end

      it "redirects to the sign_in page" do
        get :index
        expect(response).to redirect_to "users/sign_in"
      end
    end

    context "logged_in" do
      before do
        @user = FactoryBot.create(:user)
      end

      it "responds successfully" do
        sign_in @user
        get :index
        expect(response).to be_success
      end

      it "responds a 200 response" do
        sign_in @user
        get :index
        expect(response).to have_http_status "200"
      end
    end
  end
end

ユーザーの入力をテスト

createアクションを例にPOST, PATCH, DESTROYリクエストもテストしていきます。
入力のエラーもテストも忘れないようにしましょう。

spec/controllers/projects_controller_spec.rb
describe "#create" do
  context "guest" do
    it "returns a 302 response" do
      project_params = FactoryBot.attributes_for(:project)
      post :create, params: { project: project_params }
      expect(response).to have_http_status "302"
    end

    it "redirects to the sign_in page" do
      project_params = FactoryBot.attributes_for(:project)
      post :create, params: { project: project_params }
      expect(response).to redirect_to "/users/sign_in"
    end
  end

  context "logged_in" do
    before do
      @user = FactoryBot.create(:user)
    end

    context "vaild attributes" do
      it "adds a project" do
        project_params = FactoryBot.attributes_for(:project)
        sign_in(@user)
        expect{
          post :create, params: { project: project_params }
        }.to change(@user.projects, :count).by(1)
      end
    end

    context "invaild attributes" do
      it "dose not add a project" do
        project_params = FactoryBot.attributes_for(:project, :invalid)
        sign_in(@user)
        expect{
          post :create, params: { project: project_params }
        }.to_not change(@user.projects, :count)
      end
    end
  end
end

HTML以外の出力を扱う

CSVやJSONといったフォーマットでデータを返す処理のテストも見ていきます。
リクエストを送るコードで

format: :json

でフォーマットを指定し、

expect(response.content_type).to eq "application/json"

で帰ってきたデータのフォーマットを指定することでテストできます。

続き

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0