Rspecによるテスト:外部キーが設定されている際のモデルテスト
扱うモデルについて
メッセージ投稿に関するMessageモデルを例に説明していきます!
私の作成しているアプリのmessagesテーブルは以下のようになっており、
user_idとroom_idの2つを外部キーとして設定しています。
また、空での投稿を防ぐためにcontentにバリデーションをかけています。
Column | Type | Options |
------- | ------- | ----------------- |
user_id | integer | foreign_key: true |
room_id | integer | foreign_key: true |
content | string | null: false |
image | string |
外部キーを考慮せずにテストを行うと・・・
今回は"contentとimageがあれば投稿できる"という項目でテストを行います。
factory_botを使ってテンプレートを作成しました。
factory_botの説明についてはこちら↓↓
https://dkdkdk3.hatenablog.com/entry/2020/06/07/005240
spec > factories > messages.rb
FactoryBot.define do factory :message do content {"テストです。"} image {"test.jpg"} end end
テストについては以下のように記述しました。
spec > models > message_spec.rb
require 'rails_helper' describe Message do describe '#create' do it "contentとimageがあれば投稿できる" do message = build(:message) expect(message).to be_valid end end end
この内容でテストを実行すると、
1) Message#create contentとimageがあれば投稿できる Failure/Error: expect(message).to be_valid expected #<Message id: nil, content: "テストです。", image: "test.jpg", user_id: nil, created_at: nil, updated_at: nil, room_id: nil> to be valid, but got errors: Userを入力してください, Roomを入力してください
とテストは通りません。
最下部に、"got errors: Userを入力してください, Roomを入力してください"とあります。
MessageモデルにはUserとRoomモデルを外部キーに設定しており、
これらが無いためにエラーを起こしています。
テストにおける外部キーの設定方法
Messageモデルのテスト用にUserとRoomの情報をfactory_botで作成しました。
Roomに関しては個人間でチャットをするための部屋を用意しただけなので、カラムは作成していません。
spec > factories > users.rb
FactoryBot.define do factory :user do username {"test"} email {"test@gmail.com"} password {"000000"} password_confirmation {"000000"} end end
spec > factories > rooms.rb
FactoryBot.define do factory :room do end end
外部キーを使用するための準備はできました!
テストを書いていきましょう!
spec > models > message_spec.rb
require 'rails_helper' describe Message do describe '#create' do it "contentとimageがあれば投稿できる" do user = create(:user) room = create(:room) message = build(:message, user_id: user.id, room_id: room.id) expect(message).to be_valid end end end
UserとRoomの情報をcreateメソッドであらかじめ登録します。
一時的にテスト用のDBに保存しておく必要があるためです。
*buildメソッドだとDBに登録されないのでテストは通りません。
そのあとにMessageの情報を呼び出して外部キーの設定も記述します。
*この記述でテストが終わるのでbuildメソッドで大丈夫です!
Message #create contentとimageがあれば投稿できる Finished in 1.12 seconds (files took 1.59 seconds to load) 1 example, 0 failures
これでテストが通るようになりました!
ちなみに試行錯誤している途中で、
Messageのfactory_botに外部キーの情報を記述してもテストは通りました。
spec > factories > messages.rb
FactoryBot.define do factory :message do content {"テストです。"} image {"test.jpg"} user {build(:user)} room {build(:room)} end end
テストの記述はこれです。
spec > models > message_spec.rb
require 'rails_helper' describe Message do describe '#create' do it "contentとimageがあれば投稿できる" do message = build(:message) expect(message).to be_valid end end end
こっちでもテストは通るのですが、
テストを記述するファイル(spec > models > message_spec.rb)に外部キーの情報を書いておらず、
全体像が把握できないのであまり良い書き方では無いのかなと思います。