LoginSignup
1
1

RSpecで学ぶbuildとcreateの違い

Last updated at Posted at 2024-03-30

初めに

「書いて、慣れろ!」をしてると、前提知識の理解が浅いことで苦しみます。
焦らずに、知識を定着させましょう。ということで、FactoryBotのbuildとcreateについて理解できたので書きました。

問題

メールアドレスのバリデーション

validates :email, uniqueness: { case_sensitive: false }

FactoryBotでテストデータを生成

email { "info@example.com" }

テストデータで生成した小文字のメールアドレスと大文字のメールアドレス { build(:admin_user, email: 'INFO@example.com') } が重複するケースを作る

RSpec.describe AdminUser, type: :model do
  let(:admin_user) {build(:admin_user)}
  
	describe "バリデーションの検証" do
        context "メールアドレスが大文字と小文字に関わらず、重複した場合" do
	      let(:admin_user) { build(:admin_user, email: 'INFO@example.com') }
	
    	    it "大文字のメールアドレスで登録すると、無効であること" do
                admin_user_with_uppercase_email = build(:admin_user, email:'INFO@EXAMPLE.COM') 
                expect(admin_user_with_uppercase_email).to_not be_valid 
            end
    
        end
    end
end

Dockerコンテナで以下コマンドを実行

rspec spec/models/admin_user_spec.rb

バリデーションテストが失敗

Failure/Error: expect(admin_user).to_not be_valid
expected #<AdminUser id: nil, name: "AdminUser", email: "info@example.com", created_at: nil, updated_at: nil> not to be valid

解決方法

createメソッドでテスト実行前に info@example.com をデータベースに保存する

context "メールアドレスが大文字と小文字に関わらず、重複した場合" do
	before do
		create(:admin_user, email: 'info@example.com')
	end
	
	it "大文字のメールアドレスで登録すると、無効であること" do
        admin_user_with_uppercase_email = build(:admin_user, email: 'INFO@EXAMPLE.COM') 
        expect(admin_user_with_uppercase_email).to_not be_valid 
    end
end

原因

バリデーションルールの正確な理解

一意性の検証において、データを事前にデータベースに保存する必要性の認識が不足していました。小文字メールアドレスをFactoryBotで生成するだけで十分だと考えていました。

buildメソッドの挙動

オブジェクトをメモリ上にだけ生成し、データベースには保存しません。バリデーションのテストやアソシエーションの設定確認など、データベースに保存する必要がない場合に便利です。

終わりに

バリデーションルールの理解から順を追ってテストを実施することを学べました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1