Search code examples
ruby-on-railsrspecrspec-rails

"Name has already been taken" in RSpec/FactoryGirl with multiple associations


I am trying to run a very basic spec test and it fails with the error "Name has already been taken".

Update belongs to User who has many Roles.

user model

# == Schema Information
#
# Table name: users
#
#  id                     :integer          not null, primary key
#  email                  :string           default(""), not null
#

FactoryGirl.define do
  factory :user_engineer, class: User do
    id 1
    email '[email protected]'
    roles {[FactoryGirl.create(:engineer)]}
  end
end

roles model

# == Schema Information
#
# Table name: roles
#
#  id          :integer          not null, primary key
#  name        :string
#  description :text
#

FactoryGirl.define do
  factory :engineer, class: Role do
    id 3
    name 'Engineer'
    description 'He is the chosen one'
  end
end

updates model

# == Schema Information
#
# Table name: updates
#
#  id            :integer          not null, primary key
#  content       :text
#  user_id       :integer
#  ticket_id :integer
#

FactoryGirl.define do
  factory :update do
    content "This is a test update"
    association :user, factory: :user_engineer
  end
end

update_spec.rb

require 'rails_helper'

RSpec.describe Update, type: :model do
  let(:update){ FactoryGirl.create :update }
  it { expect(update).to be_valid }
end

This is the error:

Update
  example at ./spec/models/update_spec.rb:19 (FAILED - 1)

Failures:

  1) Update 
     Failure/Error: roles {[FactoryGirl.create(:engineer)]}

     ActiveRecord::RecordInvalid:
       Validation failed: Name has already been taken

How can I pass the tests?!

EDIT: By adding the sequence line I was suggested, I get the following error after running RAILS_ENV=test rake db:drop:

1) Update 
     Failure/Error: roles {[FactoryGirl.create(:engineer)]}

     ActiveRecord::RecordNotUnique:
       PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "roles_pkey"
       DETAIL:  Key (id)=(3) already exists.
       : INSERT INTO "roles" ("id", "name", "description", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"

Solution

  • As from your error it is clear that you have a uniq validation on name attribute, you should be then use sequence technique.

    FactoryGirl.define do
      factory :engineer, class: Role do
        id 3
        sequence(:name) { |n| "Engineer-#{n}" }
        description 'He is the chosen one'
      end
    end