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

#はじめに
サービスの品質を保つために必要不可欠なテストを実施しております。
今回はLikeモデル編ということで、今後他のモデルについても実施し記事にしていきたいと思います。

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

```Gemfile
  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/80092b95-ac1e-673e-91f9-b344495584e2.png)

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

```xxx_create_likes.rb
class CreateLikes < ActiveRecord::Migration[6.0]
  def change
    create_table :likes do |t|
      t.references :user,       foreign_key: true
      t.references :answer,     foreign_key: true
      t.references :definition,     foreign_key: true
      t.timestamps
    end
  end
end
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/e949d67f-b2d5-172a-7cf1-b80c5d40e4be.png)


#モデル内のバリデーション

```app/models/like.rb
class Like < ApplicationRecord
  belongs_to :user
  belongs_to :answer
  belongs_to :definition

  validates :user_id, presence: true
  validates :answer_id, uniqueness: { scope: :user_id }, presence: true
  validates :definition_id, uniqueness: { scope: :user_id }, presence: true
end

```

#FactoryBotの内訳

```spec/factories/likes.rb
FactoryBot.define do
  factory :like do
    association :answer
    association :definition
    user { answer.user }
  end
end

```

#テストコードの内容

```spec/models/like_spec.rb

require 'rails_helper'

RSpec.describe Like, type: :model do
  before do
    @like = FactoryBot.build(:like)
  end
  describe '正常値と異常値の確認' do
    context 'likeモデルのバリデーション' do
      it "user_idとanswer_id、definition_idがあれば保存できる" do
        expect(FactoryBot.create(:like)).to be_valid
      end

      it "user_idがなければ無効な状態であること" do
        @like.user_id = nil
        @like.valid?
        expect(@like.errors[:user_id]).to include("を入力してください")
      end

      it "answer_idがなければ無効な状態であること" do
        @like.answer_id = nil
        @like.valid?
        expect(@like.errors[:answer_id]).to include("を入力してください")
      end

      it "definition_idがなければ無効な状態であること" do
        @like.definition_id = nil
        @like.valid?
        expect(@like.errors[:definition_id]).to include("を入力してください")
      end

      it "answer_idが同じでもuser_idが違うと保存できる" do
        like = FactoryBot.create(:like)
        expect(FactoryBot.create(:like, answer_id: like.answer_id)).to be_valid
      end

      it "definition_idが同じでもuser_idが違うと保存できる" do
        like = FactoryBot.create(:like)
        expect(FactoryBot.create(:like, definition_id: like.definition_id)).to be_valid
      end

      it "user_idが同じでもanswer_idが違うと保存できる" do
        like = FactoryBot.create(:like)
        expect(FactoryBot.create(:like, user_id: like.user_id)).to be_valid
      end
    end
  end
end
```

#補足説明
##Factorybotのassociationメソッドについて
オブジェクト(userオブジェクト、answerオブジェクト、definitionオブジェクト）同士の関連付けを行うために使用しています。

例）
以下のようにanswerオブジェクトの記述をするためには、それに紐づくuserオブジェクトの情報を記述する必要があります。

```like_spec.rb
user = FactoryBot.create(:user)
answer = FactoryBot.create(:answer, user: user)
```

associationメソッドを使用することで、オブジェクト同士の関連付けを行えるため、以下のように1行での記述で済ませることができます。

```like_spec.rb
answer = FactoryBot.create(:answer)
```

##Factorybotのuser { answer.user }について
詳細は以下URLより。
https://qiita.com/Ryoga_aoym/items/741c57e266a9d811a2d4

以上です。