FactoryBot和Faker - 独特的不起作用

sek*_*kmo 4 ruby rspec ruby-on-rails faker factory-bot

我正在使用FactoryBot和Faker进行测试,看起来Faker正在生成相同的名称:

class Profile < ApplicationRecord
  belongs_to :user
  validates_presence_of :first_name, :last_name, :nickname
  validates :nickname, uniqueness: { case_sensitive: false }
end

FactoryBot.define do
  factory :user do
    sequence(:email) { |n| "user#{n}@example.org" }
    password "123456"
    trait :with_profile do
      profile
    end
  end
end

FactoryBot.define do
  factory :profile do
    first_name Faker::Name.unique.first_name
    last_name Faker::Name.unique.last_name
    nickname { "#{first_name}_#{last_name}".downcase }
    user
  end
end

RSpec.feature "Friendships", type: :feature do
  scenario "User can accept a pending friendship request" do
    @tom   = create(:user, :with_profile)
    @jerry = create(:user, :with_profile)
    #other stuff
  end
end
Run Code Online (Sandbox Code Playgroud)

即使我使用的是独特的方法,我也会收到错误

ActiveRecord::RecordInvalid: Validation failed: Nickname has already been taken`.
Run Code Online (Sandbox Code Playgroud)

有线索吗?

yza*_*vin 7

应该:

first_name { Faker::Name.unique.first_name }
last_name { Faker::Name.unique.last_name }
Run Code Online (Sandbox Code Playgroud)

何时Faker::Name.unique.first_name将评估加载.因此,使用块.

编辑:

FactoryBot.define do
  factory :profile do
    first_name Faker::Name.unique.first_name
  end
end
Run Code Online (Sandbox Code Playgroud)

在此示例中,Faker::Name.unique.first_name将在工厂定义期间(加载/需要文件时)评估一次.如果它找到一个唯一值,比如'John Doe',它将被用于该工厂创建的每个项目.

或者换句话说:在加载文件并Faker::Name.unique.first_name进行评估后,您可能会认为这个工厂好像是:

FactoryBot.define do
  factory :profile do
    first_name 'John Doe'
  end
end
Run Code Online (Sandbox Code Playgroud)

当您使用的块-块的身体会在每次调用时进行评估create(:profile)build(:profile).该Faker::Name.unique.first_name区块内的部分将每次调用,并返回不同的,独特的效果.