Rspec4のコントローラーテストでviewsが読み込めない!?

スポンサーリンク

はじめに

rails6とRspec4でテストを実行しようとしている方がコントローラーテストを実行作成して、なぜかrender_templateのマッチャが上手く機能しないということで質問を受けた際お伝えしたことをまとめます。

僕は普段Rspec3.7だったしコントローラーテストではなくリクエストスペックで実行していたので非常に解決に苦しみました・・・

参考サイト

Project: RSpec Rails 4.0 Controller specs

今回起きていた現象

シンプルなコントローラーspecでrender_templateの返り値が[]

最初は以下のような記述で、文法上の問題も全くないように感じていました。

require "rails_helper"

RSpec.describe ExamplesController do
    let(:user) create(:user)
    before(:each) do
        login user
    end
    describe "GET index" do
        it "renders the index template" do
          get :index
          expect(response).to render_template("index")
        end
    end
end

仮説

①loginメソッドは何か確認すると、deviseの機能を実装してテストしているということだったので、まずログインができていないのではないか?
②indexアクションを呼び出しているが、そのviewファイルは本当にあるのか、スペルミスがあるのではないか?
③そもそもviewを呼び出せるのか?
④そもそも通信できているの?

検証

①deviseのテスト導入を全部確認。

クリア
②対応するviewファイルのディレクトリ構造と名前を一から確認
クリア

③試しにlayouts/application.htnl.erbを呼んでみる。

require "rails_helper"

RSpec.describe ExamplesController do
    let(:user) create(:user)
    before(:each) do
        login user
    end
    describe "GET index" do
        it "renders the index template" do
          get :index
          expect(response).to render_template("layouts/application")
        end
    end
end

render_templateが[]になり失敗。
全部のテンプレートが呼べていない!!!

④通信ができているかhave_http_statusマッチャで確認

require "rails_helper"

RSpec.describe ExamplesController do
    let(:user) create(:user)
    before(:each) do
        login user
    end
    describe "GET index" do
        it "renders the index template" do
          get :index
          expect(response).to have_http_status(200)
        end
    end
end

200でOK!!
なぜ通信はできているのに呼び出せないんだ・・・

仮説検証の結果の仮説

render_templateのマッチャが機能していない。
または何かの要因があってテンプレートをそもそも呼んでいない。
の2択かなぁと思いました。

原因

もしかしたらRspecのバージョンが新しいのかなと思って確認したところ、Rspec4で新し目のやつだったので、バージョンによる変更違いかなと思いました。
Rspecのリファレンスやら何やらを確認しに行くことに。

Project: RSpec Rails 4.0 Controller specs

render_viewsで事前に読み込め。

見慣れたコントローラーspecの使い方が最初に書いてあったのですが、おりていき、Viewsの部分を確認すると

Views
by default, views are not rendered. See views are stubbed by default and render_views for details.

の文言が!!!!
初期設定ではなんとviewsを読み込まないらしいとのこと!!!

実際の書き方

下記のページのリンクを飛んで確認してみると・・・

Project: RSpec Rails 4.0 Controller specs Views are stubbed by default

By default, controller specs stub views with a template that renders an empty
string instead of the views in the app. This allows you specify which view
template an action should try to render regardless of whether the template
compiles cleanly.

コントローラーspecでviewファイルがレンダリングできているか確認しようとすると空の文字列が返ってくるらしいです。

読み込む前にrender_viewsでviewファイルを読み込んでから書いてくれてとのことで以下のように記述しました。

require "rails_helper"

RSpec.describe ExamplesController do
    render_views
    let(:user) create(:user)
    before(:each) do
        login user
    end
    describe "GET index" do
        it "renders the index template" do
          get :index
          expect(response).to render_template(:index)
        end
    end
end

これでなんとか解決できたか??と思いましたが403の認証エラーが返ってきてこれも頭を悩ませました笑
どういうこと?上手くいっているの???
これはrender_viewsとは全くの無関係だったので番外編に書きます笑

番外編

403のエラーが返ってくる??

なぜか認証エラーが返ってくるので、どういうことかめちゃくちゃ考えました。
相手の方に聞いてもさっぱりわからないということで正直お手上げな感じでしたが、ひらめきがやってきました。

basic認証が動いて認証エラー

僕「・・・・・・もしかしてbasic認証入れてます?」
相手の方「・・・・そんなのあったかなぁ・・・?」

念の為applicationコントローラーを確認しに行くとbeforeメソッドで全てのページにアクセスする前にbasic認証をかけていたようでした笑

なんの機能を実装しているかは把握しておいてほしいなと感じた瞬間・・・

basic認証を外すとテストが通るようになりました。よかった〜

終わりに

今回起きたことの発端としてはRspecが標準ではviewファイルを呼び出さないという現象になっていたことが要因でした。
そこに認識していなかった機能が邪魔をしていたという形です。

毎回render_viewsを書くのはめんどくさいなぁと思うので、Rspecのrails_helperに下記を書けば標準で読み込んでくれるとのこと。

RSpec.configure do |config|
  config.render_views
end

何か新しいバージョンになったらまずはリファレンスを読み込むことが重要ですね!!

タイトルとURLをコピーしました