#目的
・テストコードにおけるcreateとbuildの違いについて理解を深める
#内容
テストコードにおいて下記のコードを実行したら、
pry(#<RSpec::ExampleGroups::User::Nested>)> sign_in(@room_user.user)
NoMethodError: undefined method `user' for nil:NilClass
Did you mean? super
とのエラーコードが出ました。
userの中身が空ですといった内容のエラーです。コードは正しいと思われるのですが、何故でしょうか。
理由を深掘りしてみます。
記
require 'rails_helper'
RSpec.describe User, type: :model do
before do
@user = FactoryBot.build(:user)
#↑ここが原因
end
describe 'ユーザー新規登録' do
it "nicknameとemail、passwordとpassword_confirmationが存在すれば登録できること" do
expect(@user).to be_valid
end
it "nicknameが空では登録できないこと" do
@user.nickname = nil
@user.valid?
expect(@user.errors.full_messages).to include("Nickname can't be blank")
end
it "emailが空では登録できないこと" do
@user.email = nil
@user.valid?
expect(@user.errors.full_messages).to include("Email can't be blank")
end
it "重複したemailが存在する場合登録できないこと" do
@user.save
another_user = FactoryBot.build(:user)
another_user.email = @user.email
another_user.valid?
expect(another_user.errors.full_messages).to include("Email has already been taken")
end
it "passwordが空では登録できないこと" do
@user.password = nil
@user.valid?
expect(@user.errors.full_messages).to include("Password can't be blank")
end
it "passwordが5文字以下であれば登録できないこと" do
@user.password = "00000"
@user.password_confirmation = "00000"
@user.valid?
expect(@user.errors.full_messages).to include("Password is too short (minimum is 6 characters)")
end
it "passwordが存在してもpassword_confirmationが空では登録できないこと" do
@user.password_confirmation = ""
@user.valid?
expect(@user.errors.full_messages).to include("Password confirmation doesn't match Password")
end
end
end
#buildはデータベースに保存する機能はない
上記、
@user = FactoryBot.build(:user)
に注目すると、buildメソッドを使用しているが、createにデータベースへインスタンスを保存する役割はありません。
そのため、データベースが空という意味の
`user' for nil:NilClass
が表示されました。
#データを保存する際はcretate
当該部分を正しく訂正すると
@user = FactoryBot.create(:user)
となります。
buildに対してcretateはデータベースへアクセスし、インスタンスを保存する役割があります。
では、buildを使用する理由はなんでしょうか。
buildはデータベースへのアクセスという処理がない分、createよりも処理が早いというメリットがあります。
膨大なデータを扱う際のテストはcreateの必要がない部分はbuildを用いる方が良いでしょう。
#総括
create:DBにインスタンスを保存する
build:メモリに一時的にインスタンスを生成する
テストにおいて、データベースにアクセスする必要がある処理にはcreate。一方、アクセスする必要ないものはbuildを用いる。buildはアクセスがない分、自動化テストの処理が早くなるメリットがある。