テストコードで「basic認証が通らないエラー」を対応"出来なかった話"


エラー時の状況

某フリマサイトのコピーアプリを実装したので、練習としてコントローラーの単体テストコードを記述していたところ、実行時にターミナル上で下記エラーが発生しました。

ターミナル
bundle exec rspec spec/requests/items_spec.rb

~中略~

 1) ItemsController GET #index indexアクションにリクエストすると正常にレスポンスが返ってくる
     Failure/Error: expect(response.status).to eq 200

       expected: 200
            got: 401

       (compared using ==)
     # ./spec/requests/items_spec.rb:20:in `block (3 levels) in <top (required)>'

~中略~
開発環境

Ruby 2.6.5
Rails 6.0.3.3
MySQL
Visual Studio Code
(Caprybara,Rspec,GoogleChrome)

考察・検証

root_pathへのアクセス時にHTTPステータスが401になっている(アクセスできていない)、というエラーな模様。
本アプリケーションはbasic認証を導入しており、それがが関係しているのではと予想しました。

basic認証とは

HTTP通信の規格に備え付けられているユーザー認証の仕組みのことで、Webサイトにアクセス制限をかけることのできる簡易的な方法の一つです。
サーバーとの通信が可能なユーザーとパスワードをあらかじめ設定しておき、それに一致したユーザーのみが、Webアプリケーションを利用できるようにします。

【サンプル画像】

上記エラー文とbasic認証で調べた所、やはりテスト時にbasic認証が通らない事例が見受けられました。
参考記事(記事末に掲載)を元に、テスト時のリクエストにbasic認証のユーザー名とパスワードをどうにか渡せないかと試してみました。

結果

メンターさんを交えて格闘すること約2時間…
参考記事を元に様々な方法を試みるもエラーは解決せず。
そして、メンターさんが調べたところ…
「2020年現在、テスト時のbasic認証は推奨されていない」とのことでした。

なんてこった…!

〜出来ぬなら、やらぬ〜

エラー解決の方針を「テスト時にbasic認証を通す」から、
「本番環境以外(テスト時)はbasic認証をしない」へ変更。

application_controller.rb
class ApplicationController < ActionController::Base
  before_action :basic_auth if Rails.env.production? # テスト時はbasic認証を行わないように分岐

  private
  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == 'username' && password == 'password'
    end
  end
end

※usernameとpasswordは、実際は環境変数で設定しています。

before_actionにif Rails.env.production?を追記して、本番環境でのみ適用するようにしました。
お陰で、テスト時はbasic認証せずそのままトップページへアクセスし、テストを実行できるようになりました!

感想

まだまだ初学者なこともあり、エラーに直面すると問題箇所を真正面から解決しようとしがちです。
今回のように、エラーを避ける、「やらずに済む」方法が無いかと多方面から考えることも重要だと実感しました。

本記事が初投稿でした。少しでも参考になれば嬉しく思います。
最後まで閲覧いただき、誠にありがとうございました。

参考記事

ベーシック認証(Basic認証)とは?設定方法と注意点・エラーになる原因を解説
Rails×Basic認証×Rspecでつまづいた
RSpec3でBASIC認証がかかったアクションをテストする
Rails/Rspecテストをhttp基本認証で渡す
Basic認証を交えたテストコードの書き方

修正履歴

2020/10/25
ご指摘いただき、下記修正いたしました。

  • 非推奨については口頭のみで伺った話でソース元が不確かなので、打ち消し線を入れました。(「そんな噂がある」程度に捉えていただければと思います。)

  • 要は、エラーを対応出来なかった話なので、タイトルを変更しました。

@jnchito様、ありがとうございました。