【Rails6】 RSpecによる投稿時のモデル単体テストの実装

#はじめに
サービスの品質を保つために必要不可欠なテストを実施しております。
今回は投稿時のモデル（Definitionモデル）単体テストを行い、その内容を記事にしました。
今後他のモデルについても実施し記事にしていきたいと思います。

またテストは追加で行って参りますので、今後も投稿時のモデル単体テストの内容を追加していきます。

#前提
・以下のgemはインストール済み

```
  gem 'rspec-rails', '~> 4.0.0'
  gem 'factory_bot_rails'
  gem 'faker'
```

・投稿機能実装済み

#バージョン
rubyのバージョン　ruby-2.6.5
Railsのバージョン Rails:6.0.0
rspec-rails 4.0.0

#実施したテスト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/0ab0c9e7-a2d1-0023-a792-826ffd3ff484.png)

#definitionsテーブルのカラムの紹介

```xxx_create_definitions.rb
class CreateDefinitions < ActiveRecord::Migration[6.0]
  def change
    create_table :definitions do |t|
      t.text       :title,          null: false
      t.text       :body,           null: false
      t.references :user,           foreign_key: true
      t.timestamps
    end
  end
end

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/c54a0221-0a97-331d-0290-5bfaedc330eb.png)


#モデル内のアソシエーションとバリデーション

```app/models/definition.rb
class Definition < ApplicationRecord
  belongs_to :user
  has_many :answers, dependent: :destroy
  has_many :reviews, dependent: :destroy
  has_many :notifications, dependent: :destroy
  has_many :likes, dependent: :destroy

  validates :title, presence: true
  validates :body, presence: true

# 〜省略〜
```

#FactoryBotの内訳

```spec/factories/definitions.rb
FactoryBot.define do
  factory :definition do
    title                        {Faker::Lorem.sentence}
    body                         {Faker::Lorem.sentence}
    association :user
  end
end
```

#テストコードの内容

```spec/models/definition_spec.rb
require 'rails_helper'

RSpec.describe Definition, type: :model do
  before do
    @definition = FactoryBot.build(:definition)
  end

  describe '投稿' do
    context '投稿がうまくいくとき' do
      it "内容に問題ない場合" do
        expect(@definition).to be_valid
      end
      it "正しく保存できるか" do
        expect(FactoryBot.build(:definition)).to be_valid
      end
    end

    context '投稿が上手くいかないとき' do
      it "titleが空だと登録できない" do
        @definition.title = ''
        @definition.valid?
        expect(@definition.errors.full_messages).to include("Titleを入力してください")
      end
      it "bodyが空だと登録できない" do
        @definition.body = ''
        @definition.valid?
        expect(@definition.errors.full_messages).to include("Bodyを入力してください")
      end
     end
  end


  describe "各モデルとのアソシエーション" do
    let(:association) do
      described_class.reflect_on_association(target)
    end
    let(:definition) { FactoryBot.create(:definition) }

    context "Likeモデルとのアソシエーション" do
      let(:target) { :likes }
      it "Likeとの関連付けはhas_manyであること" do
        expect(association.macro).to eq :has_many
      end

      it "Defintionが削除されたらLikeも削除されること" do
        like = FactoryBot.create(:like, definition_id: definition.id)
        expect { definition.destroy }.to change(Like, :count).by(-1)
      end
    end

    context "Answerモデルとのアソシエーション" do
      let(:target) { :answers }
      it "Answerとの関連付けはhas_manyであること" do
        expect(association.macro).to eq :has_many
      end

      it "Definitionが削除されたらAnswerも削除されること" do
        answer = FactoryBot.create(:answer, definition_id: definition.id)
        expect { definition.destroy }.to change(Answer, :count).by(-1)
      end
    end
  end
end
```

以上です。