RailsアプリでFactoryBotを使ってアソシエーションのテストをしたい
Rails6でログインユーザーがカテゴリーごとに投稿できるシステムを作っています。
FactoryBotを使わずに毎回親のモデルと子のモデルを作っていた時は問題なかったのですが、Everyday Railsを参考にしてFactoryBotを使ってアソシエーションのテストコードを書いていると、子のモデルに必須項目となっている外部キーがセットされていないというエラーが表示されてしまって困っています。
以下がシステムのモデル概要と、もともとのテストコード、そしてFactoryBotを使ったテストコードです。
システムのモデル構成
3つのモデルUser
,Category
,Post
があり、PostはUserとCategoryに紐付くモデルになっています。
Post.user_id
とPost.category_id
はどちらもモデルの定義で必須項目としています。
app/models/post.rb
ruby
1class Post < ApplicationRecord 2 belongs_to :category 3 belongs_to :user 4 5 validates :content, :user_id, :category_id, presence: :true 6end
app/models/category.rb
ruby
1class Category < ApplicationRecord 2 has_many :posts 3end
app/models/user.rb
ruby
1# Deviseで作られたUserモデル 2class User < ApplicationRecord 3 devise :database_authenticatable, :registerable, 4 :recoverable, :rememberable, :validatable 5 6 validates :name, presence: true, uniqueness: true 7 8 has_many :posts 9end
となっています。
もともとはRSpecのテストコードは以下でした。
spec/models/post.rb
ruby
1...略 2user = User.create(name: "test", email: "test@test.com") 3category = Category.create(title: "test") 4post = Post.new(content: "test", user_id: user.id, category_id: category.id) 5expect(post).to be_valid 6...略
この時点ではテストコードは問題ありませんでしたが、FactoryBotを使ってアソシエーション部分をFactoryのコードにまとめることにしました。以下が変更後の各コードです。
spec/factories/users.rb
ruby
1FactoryBot.define do 2 factory :user do # 3 sequence(:name) { |n| "tester#{n}"} 4 sequence(:email) { |n| "tester#{n}@example.com"} 5 password {"Test1234"} 6 end 7end
spec/factories/categories.rb
ruby
1FactoryBot.define do 2 factory :category do 3 title {"test"} 4 end 5end
spec/factories/posts.rb
ruby
1FactoryBot.define do 2 factory :post do 3 content {"test content"} 4 association :user 5 association :category 6 end 7end
以上が各Factoryの定義。
そして、Postモデルのテストコードが以下の通りです。
ruby
1...略 2post = FactoryBot.build(:post) 3expect(post).to be_valid
すると、以下のようなエラーが発生しました。
発生している問題・エラーメッセージ
Failure/Error: expect(post).to be_valid expected #<Post id: nil, content: "test content", created_at: nil, updated_at: nil, category_id: nil, user_id: nil> to be valid, but got errors: User can't be blank, Category can't be blank
試したこと
spec/models/post.rbでUserとCategoryもFactoryBotを使って作ると正常に動作します。
spec/models/post.rb
ruby
1user = FactoryBot.create(:user) 2category = FactoryBot.create(:category) 3post = FactoryBot.build(:post, user_id: user.id, category_id: category.id) 4expect(post).to be_valid
FacotryBotを使うとspec/factories/posts.rbでアソシエーションを定義してものが自動的にセットされると思っているのですが、結局使用時にすべてcreateして属性にセットしなければいけないのでしょうか?
ちなみにEveryday RailsではUserモデルでエイリアスを使っていましたが、あまり理解できなかったのでエイリアスは使っていません。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/01/04 00:21
2021/01/04 00:24