Faker在factory_girl中使用时正在生成重复数据


86

我正在尝试使用Faker gem将一些虚假数据填充到工厂中:

Factory.define :user do |user|
  user.first_name Faker::Name::first_name
  user.last_name Faker::Name::last_name
  user.sequence(:email) {|n| "user#{n}@blow.com" }
end

但是,尽管我希望这会产生具有不同的first_name和last_names的用户,但每个用户都是相同的:

>> Factory(:user)
=> #<User id: 16, email: "user7@blow.com", created_at: "2011-03-18 18:29:33",     
updated_at: "2011-03-18 18:29:33", first_name: "Bailey", last_name: "Durgan">
>> Factory(:user)
=> #<User id: 17, email: "user8@blow.com", created_at: "2011-03-18 18:29:39", 
updated_at: "2011-03-18 18:29:39", first_name: "Bailey", last_name: "Durgan">

如何获得Faker gem为每个用户生成新名称,而不仅仅是重用原始名称?


1
只是在黑暗中拍摄,但是您是否尝试过使用类似的东西user.sequence(:first_name} {|n| Faker::Name::first_name}?当加载“夹具”时,FactoryGirl可能只是评估您的Faker调用。使用该sequence param,&block方法应避免这种情况。
史蒂文

Answers:


156
Factory.define :user do |user|
  user.first_name { Faker::Name::first_name }
  user.last_name { Faker::Name::last_name }
  user.sequence(:email) {|n| "user#{n}@blow.com" }
end

尝试在假冒者周围放上括号。看到这个链接


8
我非常喜欢stackoverflow-谢谢您,您保存了我的培根
Peter Nixey

谢谢,这解决了我的问题!
橘子13

5
为什么,为什么,为什么?这里发生了什么?
jordanpg


9
遗憾的是,这并不总是有效。这基本上只是获得一个新的随机伪造对象,但是由于存在RNG,仍然有可能失败。
Michael Lynch

45

请注意,由于可用的假数据数量有限,Faker可能仍在提供重复数据。

为了简单的测试目的并通过唯一性验证,我使用了以下内容:

sequence(:first_name) {|n| Faker::Name::first_name + " (#{n})"}
sequence(:last_name) {|n| Faker::Name::last_name + " (#{n})"}

3
这个答案值得更多的赞扬。当您的测试创建大量实例时,很可能会发生这种情况。
Enrico Carlesso 2015年

是的,我同意恩里科的观点。+1
卡林根2015年

不错,但是如果您使用名字和姓氏来生成电子邮件,或者添加了格式验证(不知道任何带有括号:P的名称),则添加括号会破坏其余部分。
西里尔·杜松-多丽丝

18

为了保留正确的答案,这里的答案是从博客转移过来的,我不认为答案是正确的。

如果您使用下面的代码,伪造者将不会生产出唯一的名称

Factory.define :user do |u|
  u.first_name Faker::Name.first_name
  u.last_name Faker::Name.last_name
end

但是,在假冒者周围放上花括号可以使其正常工作!

Factory.define :user do |u|
  u.first_name { Faker::Name.first_name }
  u.last_name { Faker::Name.last_name }
end

为了解释原因,第一个示例产生了相同的名称。它只评估一次。第二个示例在每次使用工厂时进行评估。

这是由于{}提供了惰性评估。本质上,它们以Faker调用提供proc / lambda作为其返回值。


感谢您发布此信息。我不知道为什么Faker无法生成随机数据,而且我遇到的每个示例似乎都显示了如何使用测序,这对我来说似乎很奇怪。我想使用Faker,所以每个记录都是随机的,而不是顺序的。只需在我的Faker电话上加上括号即可解决问题。简洁大方!
Blimey85 '16

5

在对属性进行唯一性验证时,使用序列的一种(效率较低的)替代方法是检查提议的值是否已经存在,并继续尝试新的值,直到其唯一为止:

FactoryGirl.define do
  factory :company do
    name do
      loop do
        possible_name = Faker::Company.name
        break possible_name unless Company.exists?(name: possible_name)
      end
    end
  end
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.