RSpecでの「dependent: destoy」のテストにてエラー:「バリデーションに失敗しました」の解消方法について

投稿者: Anonymous

解決したいこと

rspec実行時、下記のエラーが出てテストが失敗になります。こちらのエラー解決方法についてお伺いしたいです。
「これっぽい」といったような、推測される原因レベルのご回答でも大変有難いため、お願いしたく存じます。

Failures:
  1) User dependent: destoy destroys all posts when deleted
     Failure/Error: 2.times { FactoryBot.create(:post, user: user) }

     ActiveRecord::RecordInvalid:
       バリデーションに失敗しました: Create userを入力してください

「Create userを入力してください」と出ていますが、
FactoryBotで作成したuserを使っているため、userは作成されていると考えておりました。
アソシエーションを伴うFactoryBotでのテストデータの作成方法が誤っているのではないかと
推測しています。
並行して「アソシエーションを伴うFactoryBotでのテストデータの作成方法」を調べているのですが、エラーの解消方法が見当たらず、お伺いしたい次第です。

現状

ログインユーザの情報を格納するuserモデルの単体テストを実施しようとしています。

<対象テストコード(models/user_spec.rb)>

require 'rails_helper'

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.create(:user) }

  # 削除の依存関係
  describe "dependent: destoy" do
    # 削除すると、紐づく店舗も全て削除されること
    it "destroys all posts when deleted" do
      2.times { FactoryBot.create(:post, user: user) }
      expect { user.destroy }.to change(user.posts, :count).by(-2)
    end
  end
end

テストデータ:FactoryBotの中身

factories/users.rb

FactoryBot.define do
  factory :user do
    sequence(:email) { |n| "test#{n}@gmail.com" }
    password { "passwd" }
  end
end

factories/posts.rb

FactoryBot.define do
  factory :post do
    sequence(:title) { |n| "テスト投稿#{n}"}
    description {"口コミのテストです"}
    prefecture_code {"1"}
    rest_type {"1"}
    association :user
    association :community
  end
end

modelの中身

userモデルでは、post(投稿)などの他のモデルとアソシエーションがあり、
userモデルのレコードが削除されると、それに紐づくpostモデルのレコードも削除されるようになっています。具体的なコードは以下です。

user.rb(抜粋)

class User < ApplicationRecord
  has_many :posts, dependent: :destroy
end

post.rb(抜粋)

class Post < ApplicationRecord
    belongs_to :user
end

試したこと

①user_spec.rbの対象のテストケースの中でcreate userすべきかと考え、
以下のテストコードを記述しましたが、変わらず同じエラーが出ました。

  # 削除の依存関係
  describe "dependent: destoy" do
    # 削除すると、紐づく店舗も全て削除されること
    it "destroys all posts when deleted" do
      post_user = FactoryBot.create(:user)
      2.times { FactoryBot.create(:post, user: post_user) }
      expect { post_user.destroy }.to change(post_user.posts, :count).by(-2)
    end
  end

②2.timesを辞めて、postは1回のみcreateするようにして-1されるかを見るように修正しても、全く同じエラーが出るままでした。

③該当テストケースのitの中でPostをcreateする記述に変えると、下記のエラーが出るようになりました。
<user_spec.rb>

  # 削除の依存関係
  describe "dependent: destoy" do
    # 削除すると、紐づく店舗も全て削除されること
    it "destroys all posts when deleted" do
      post_user = FactoryBot.create(:user)
      Post.create(title: "1"*6, description:"1"*10, rest_type:"1", prefecture_code:"1", user_id:post_user.id)
      expect { post_user.destroy }.to change(post_user.posts, :count).by(-1)
    end

<エラー内容>

  1) User dependent: destoy destroys all posts when deleted
     Failure/Error: expect { post_user.destroy }.to change(post_user.posts, :count).by(-1)
       expected `Post::ActiveRecord_Associations_CollectionProxy#count` to have changed by -1, but was changed by 0

⇒「ユーザを消しても、紐づく投稿が消えなかった」ということかと思いますが、
 userのmodelには has_many :posts, dependent: :destroy 、postのモデルには belongs_to :user と記述しています。

申し訳ありませんが、まだRspecを学習し始めたばかりなこともあり、
基本的な箇所で見逃している点等あるかもしれないです。
不明点や追加必要な情報ございましたら、ご教示いただけますと幸いです。

また、tetatailにも同じ質問をしております。
teratails側の質問に何か更新があり次第、すぐこちらにも反映させていただきますので、
何卒ご了承ください。
【RSpec】「dependent: destoy」のテストにてエラー:「バリデーションに失敗しました」の解消方法について

よろしくお願いいたします。

解決

「バリデーションに失敗しました: Create userを入力してください」というメッセージ読み取れるのは、何かのモデルでvalidationを実行した時に、create_userというフィールドにpresence: true(もしくはそれ相当)な制約が存在するのに、create_userというフィールドがnilだったので、validationに失敗したということです。

コードから推測するに、
Postモデルには、userフィールドではなくcreate_userというフィールドが存在するのではないでしょうか?(もしくは両方とも存在しているかもしれませんが。)
models/post.rbの中身やdb/schema.rbの中身を確認してみるとどうでしょうか?
また、FactoryBot.create(:post, create_user: user)としてあげたら直ったりしないでしょうか?

もしくは、create_userというキーワードでコード内を検索をしてみるとなにか問題が見つけられるかもしれません。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *