はじめに
RSpecテストで「bundle exec rspec」を実行したところ以下のようなエラーが発生しました。
An error occurred while loading ./spec/models/user_spec.rb.
Failure/Error: require_relative '../config/environment'
FrozenError:
can't modify frozen Array: ["/usr/local/bundle/gems/turbo-rails-2.0.5/app/channels", "/usr/local/bundle/gems/turbo-rails-2.0.5/app/controllers", "/usr/local/bundle/gems/turbo-rails-2.0.5/app/controllers/concerns", "/usr/local/bundle/gems/turbo-rails-2.0.5/app/helpers", "/usr/local/bundle/gems/turbo-rails-2.0.5/app/models", "/usr/local/bundle/gems/turbo-rails-2.0.5/app/models/concerns", "/usr/local/bundle/gems/turbo-rails-2.0.5/app/jobs", "/usr/local/bundle/gems/actiontext-7.1.3.4/app/helpers", "/usr/local/bundle/gems/actiontext-7.1.3.4/app/models"]
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/engine.rb:581:in `unshift'
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/engine.rb:581:in `block in <class:Engine>'
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/initializable.rb:32:in `instance_exec'
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/initializable.rb:32:in `run'
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/initializable.rb:61:in `block in run_initializers'
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/initializable.rb:50:in `each'
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/initializable.rb:50:in `tsort_each_child'
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/initializable.rb:50:in `each'
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/initializable.rb:50:in `tsort_each_child'
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/initializable.rb:60:in `run_initializers'
# /usr/local/bundle/gems/railties-7.1.3.4/lib/rails/application.rb:426:in `initialize!'
# ./config/environment.rb:5:in `<main>'
# ./spec/rails_helper.rb:5:in `require_relative'
# ./spec/rails_helper.rb:5:in `<main>'
# /usr/local/bundle/gems/bootsnap-1.18.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
# /usr/local/bundle/gems/zeitwerk-2.6.16/lib/zeitwerk/kernel.rb:34:in `require'
# ./spec/models/user_spec.rb:1:in `<main>'
このエラーについて、調査した結果Google認証が原因であることがわかり、修正することで解決しました。この記事では、その解決方法についてまとめております。
環境
- ruby 3.2.3
- rails 7.1.3
- Docker
- RSpec
- 認証はSocery
前提として、Sorceryによるログイン機能とGoogle認証が導入済みであることを想定しています。
結論
config>initializers>socery.rb
の160行目付近にあるGoogle認証設定のcallback_url
が原因でした。以下のように、テスト環境と本番環境で設定を分けることでエラーが解消しました。
# クレデンシャル読み込み
config.google.key = Rails.application.credentials.dig(:google, :google_client_id)
config.google.secret = Rails.application.credentials.dig(:google, :google_client_secret)
# 問題のコード
if Rails.env.test?
config.google.callback_url = 'http://localhost:3000/test_callback'
else
config.google.callback_url = Settings.sorcery[:google_callback_url]
end
変更前のコード
# クレデンシャル読み込み
config.google.key = Rails.application.credentials.dig(:google, :google_client_id)
config.google.secret = Rails.application.credentials.dig(:google, :google_client_secret)
# 問題のコード
config.google.callback_url = Settings.sorcery[:google_callback_url]
config.google.user_info_mapping = { email: "email", name: "name" }
なぜこのエラーが起きるのか?
テスト(RSpec)を実行するときに、本番環境で使うリダイレクトURIが原因でエラーが発生したらしく、この設定がないとGoogle認証が動かないということらしいです。
なので、テストのときは実際のGoogle認証を使わないで、代わりに「http://localhost:3000/test_callback
」 っていうダミーのURLを使うことにしました。
本番環境では、ちゃんとしたGoogle認証が必要なので、元々の設定「Settings.sorcery[:google_callback_url]
」をそのまま使うことにしました。
その他に試したこと
Gemfile.lockの削除と再生成
rm Gemfile.lock
bundle install
Dockerコンテナの再ビルド
docker-compose build
docker-compose up
参考記事
エラー対処
同様のエラー記事
こちらも試してみました
Google認証実装
こちらの記事を見れば一通り実装できます。
こちらの記事と併用すると実装しやすいかと思われます。
おわりに
RSpecでテストを実行することは少ないかもしれませんが、動作確認には重要です。この記事がお役に立てれば幸いです。ご指摘や気になる点があれば、ぜひ教えてください。