はじめに
初めまして、うりぼーと申します。
現在プログラミングスクールでWebエンジニアを目指してRubyonRailsを中心に学習中です。
初学者ということもあり、知識不足な点も多いかと存じますが、自分がつまづいた点や勉強になったことを記事にしていけたらと思いますので、同じ初学者の方の参考になればと思います。(もちろん現役エンジニアの方のご指摘もお待ちしております!)
RspecでFactoryBotを使おうとしたら「Factory already registered」にハマってしまった話
さて本題ですが、スクールの卒業課題として作っていた書籍管理アプリのテストをRspecで書いていたらFactoryBotでハマってしまいましたので反省も込めて書いていこうと思います。
環境
ruby 2.6.5
Rails 5.2.4.1
概要
書籍(Book)モデルのCRUD機能も一通り出来上がったのでRspecでテストをするべくFactoryBotで書籍のデータを下記のように書いていました。
FactoryBot.define do
factory :book do
title { 'hoge' }
author { 'fuga' }
user
end
end
そしてspec.rbにテスト内容を書く上でルーティングを確認しようとターミナル上で「rails routes」コマンドを実行したところ、
rails aborted!
FactoryBot::DuplicateDefinitionError: Factory already registered: book
ということで「Factoryはすでに登録されているよ」というエラーを頂戴することとなりました。
(こうした名前空間のエラーはrailsコマンドなども打てなくなるようです 参考:https://shikasen-engineer.com/error_factorygirl/ )
原因調査
「これしかbookのFactoryは作ってないはずなのでおかしいなぁ」と原因もあまり思い当たらなかったためググってみると以下の記事に出会いました。
rspecとfactorybotを導入するときにハマった時に確認したこと
https://qiita.com/yukiyoshimura/items/ca60a712fb705cf9bf89
まさに同じ悩みだなぁと思い参考にさせていただくことに。
対処方法として書かれている点を私なりに解釈したところ、
- ターミナルで実行
- ファイル名の確認(_spec.rbになっているか)
- factory_bot.rbと二重設定となってしまっている
- 「rails c」によるデバッグ
- springに起因
という感じ。ただし、1,2に関しては問題なく、3の「factory_bot.rb」も作成していなかったため該当しませんでした。また、5のspringについては自分の環境で起動はしていたため、当初これが原因かと思い調べはしたものの直接的な解決には至らず…。
そこで、4の「rails c」でデバッグをすることに。現状だとrailsコマンドも使えないため一度spec/factories/books.rbをコメントアウトして試してみることに。
「Factory already registered: book」となっていたので試しに「FactoryBot.create(:book)」をしたらどうなるのかを調べてみることにしました。
irb(main):001:0> FactoryBot.create(:book)
(0.2ms) SAVEPOINT active_record_1
(0.4ms) ROLLBACK TO SAVEPOINT active_record_1
Traceback (most recent call last):
1: from (irb):1
ActiveRecord::RecordInvalid (バリデーションに失敗しました: Userを入力してください, Titleを入力してください, Authorを入力してください)
バリデーションに引っかかったものの作成自体はできそう。ということはやはりエラー文通り実際に定義がされている?
全件検索をかけてみることに。
FactoryBot.define do
factory :book do
end
end
**ありました。**testディレクトリに自動生成されていたファイルを気づかずに放置してしまっていたことが原因でした。testディレクトリはもう一つのテストフレームワークのMinitest用のディレクトリで、specディレクトリを使うRspecでは不要です。何を当たり前のことを
$ rm -r ./test
上記コマンドでtestディレクトリを削除し、spec/factories/books.rbのコメントアウトを外したところ正常に動作し無事解決となりました。
また、今後こうしたことが発生しないようにconfig/application.rbに以下を記載しtestディレクトリの自動生成を止めることにします。
(参考:https://keruuweb.com/rails-generate%E6%99%82%E3%81%ABtest%E3%82%92%E7%94%9F%E6%88%90%E3%81%97%E3%81%AA%E3%81%84/ )
class Application < Rails::Application
config.generators do |g|
g.test_framework false
end
end
まとめ
気づいてしまえば非常に単純なケアレスミスでしたが、自動生成の利便性に普段から頼り切ってしまっていたことを猛省するミスとなりました。
不要なものについても生成されないよう管理してアプリ開発していきたいと思います!