Rails の RSpec テストで不正なリクエストをどのように処理しますか?

概要

私のテスト データベースには、API 専用の Rails 5 アプリで API 呼び出しを行っているレビューがあります。

これまでのところ、インデックスのテストを作成し、ReviewController のアクションを表示しました。

エラー/不正なリクエストの処理はどのようにすればよいですか?たとえば、誰かが存在しないルートに移動しようとした場合、または誰かが既存の ID なしで show Route に移動しようとした場合、RSpec ではどのように行われるのでしょうか?

# spec/controllers/api/v1/reviews_controller_spec.rb
require 'rails_helper'

RSpec.describe Api::V1::ReviewsController do
  describe "GET #index" do
    before do
      get :index
    end

    it "returns HTTP Success" do
      expect(response).to have_http_status(:success)
    end

    it "JSON body response contains expected review attributes" do
      json_response = JSON.parse(response.body)
      json_response["status"].should == "SUCCESS"
    end
  end

  describe "GET #show" do
    before do
      get :show, params: { id: 1 }
    end

    it "returns HTTP Success" do
      expect(response).to have_http_status(:success)
    end

    it "JSON body response contains expected review attributes" do
      json_response = JSON.parse(response.body)
      json_response["status"].should == "SUCCESS"
    end
  end
end

レビューコントローラー:

# spec/controllers/api/v1/reviews_controller.rb
module Api
  module V1
    class ReviewsController < ApplicationController
      def index
        @reviews = Review.order(created_at: :desc)
        render json: { status: 'SUCCESS', message: 'loaded reviews', data: @reviews }
      end

      def show
        @review = Review.find(params[:id])
        render json: { status: 'SUCCESS', message: 'loaded the review', data: @review }
      end

      private

      def review_params
        params.require(:review).permit(:title, :star, :content, :name, :date)
      end
    end
  end
end

解決策

コントローラーのテストでは、ID が存在しない場合にコントローラーが ActiveRecord::RecordNotFound を生成するように指定できます。

describe "GET #show" do
  context "with a valid id" do
    before { get :show, params: { id: 1 } }

    it "returns HTTP Success" do
      expect(response).to have_http_status(:success)
    end

    it "JSON body response contains expected review attributes" do
      json_response = JSON.parse(response.body)
      json_response["status"].should == "SUCCESS"
    end
  end

  context "with an invalid id" do
    it "raises an error" do
      expect { 
        get :show, params: { id: "invalid-identifier" }
      }.to raise_error ActiveRecord::RecordNotFound
    end
  end
end

本番環境でコントローラーが ActiveRecord::RecordNotFound を発生させると、デフォルトが変更されていない場合、Ruby on Rails は 404 (見つからない) を返すことに注意してください。この動作の詳細については、Rails ガイドを参照してください。