コード
- spec/models/client_spec.rb
require 'rails_helper'
RSpec.describe Client, type: :model do
it "is valid with default" do
client = FactoryBot.create(:client)
expect(client).to be_valid
end
end
- spec/models/client_spec.rb
FactoryBot.define do
factory :client do
sequence(:id) { |n| n } # シーケンスを使う
sequence(:name) { |n| "クライアント#{n}" }
created_at { Time.current }
updated_at { Time.current }
end
end
概要
タイトルの通りだが、上記のコードでrspecを実行すると以下のエラーが発生する
Running via Spring preloader in process 160
F
Failures:
1) Client is valid with default
Failure/Error: client = FactoryBot.create(:client)
ActiveRecord::RecordNotUnique:
Mysql2::Error: Duplicate entry '1' for key 'clients.PRIMARY'
# /usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `_query'
# /usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `block in query'
# /usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:130:in `handle_interrupt'
# /usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:130:in `query'
# /usr/local/bundle/gems/rack-mini-profiler-2.3.4/lib/patches/db/mysql2/alias_method.rb:22:in `query'
# /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/evaluation.rb:18:in `create'
# /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/strategy/create.rb:12:in `block in result'
# /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/strategy/create.rb:9:in `tap'
# /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/strategy/create.rb:9:in `result'
# /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/factory.rb:43:in `run'
# /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/factory_runner.rb:29:in `block in run'
# /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/factory_runner.rb:28:in `run'
# /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/strategy_syntax_method_registrar.rb:28:in `block in define_singular_strategy_method'
# ./spec/models/client_spec.rb:5:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Mysql2::Error:
# Duplicate entry '1' for key 'clients.PRIMARY'
# /usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `_query'
Finished in 0.06375 seconds (files took 4 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/models/client_spec.rb:4 # Client is valid with default
原因
-
Mysql2::Error: Duplicate entry '1' for key 'clients.PRIMARY'
つまり、clientsのidが他のケースと重複しているため - FactoryBotのGitHubのページに以下のような記述があり、自分としてはFactoryBotはfixtureの代替であるため、fixtureの書き方を踏襲するものだと思った
factory_bot is a fixtures replacement
(訳: factory_bot はフィクスチャの代替品です。)
- そのため
spec/models/client_spec.rb
にはidやcreated_at、updated_atといったDBで採番されるものをコードに書いていた。 - しかしFactoryBotのWrong Wayとしても紹介されているが、独自SEQUENCE IDとして推奨されていない
対処
- spec/models/client_spec.rbで独自SEQUENCE IDなコードを削除する
FactoryBot.define do
factory :client do
sequence(:name) { |n| "クライアント#{n}" }
end
end
- テストを実行し、passすることを確認
root@99008ab20f76:/app# rspec spec/models/client_spec.rb
Running via Spring preloader in process 181
.
Finished in 0.09304 seconds (files took 4.34 seconds to load)
1 example, 0 failures