在FactoryGirl中,构建(build)方法和创建(create)方法之间有什么区别?

112

Factory Girl介绍清楚地解释了FactoryGirl.build()FactoryGirl.create()之间的区别:

# Returns a User instance that's not saved
user = FactoryGirl.build(:user)

# Returns a saved User instance
user = FactoryGirl.create(:user)

我还是不明白这两者之间的实际区别。有人能举个例子,说明在什么情况下你会选择使用其中一个而不是另一个吗?谢谢!
3个回答

148

create() 方法会将模型实例持久化到数据库中,而 build() 方法仅在内存中保存。

个人而言,只有当必须进行持久化时才使用 create() 方法,因为向数据库写入会使测试变得耗时。

例如:

我使用 create() 方法创建用户进行身份验证,因为我的身份验证引擎需要查询数据库。

如果要检查模型是否具有属性,则可以使用 build() 方法,因为不需要访问数据库。

it{Factory.build(:user).should respond_to(:name)}

更新

“在构建关联时,有一个例外情况,即您的关联不再存在于内存中,而是已持久化。请记住这一点。”--Shakes


21
在建立关联时,有一个例外情况,即构建实际上会“创建”关联,即您的关联不再存在于内存中,而是持久化保存在数据库中。请记住这一点。 - Shakes
@Shakes,我已经不再使用Rails了。 我会尽快查看。 - Helio Santos
有人制作了一个工具来将每个create实例替换为build,并在测试失败时撤消它吗? - mgold
#create 方法会从磁盘中读取并返回持久化的对象,还是返回在内存中持久化后的对象?换句话说,执行 create(...) 是否等同于 create(...).reload - Dennis

21
使用FactoryGirl.build(:factory_name)不会将数据持久化到数据库中,也不会调用save!,因此您的Active Record验证将不会运行。这样做速度更快,但验证可能很重要。
使用FactoryGirl.create(:factory_name)会将数据持久化到数据库中,并将调用Active Record验证。这显然比较慢,但可以捕获验证错误(如果您在测试中关心此类错误)。

15
或者,你可以直接使用 FactoryGirl.build(:factory_name).valid?,这样会运行验证但不保存到数据库中。 - jinavar1

5
FactoryGirl.create()会创建新的对象并为其创建关联(如果工厂有任何关联)。它们都将保存在数据库中。此外,它将触发模型和数据库验证。 回调after(:build)after(:create)将在工厂被保存后调用。同时,before(:create)将在工厂被保存之前调用。 FactoryGirl.build()不会保存对象,但如果工厂有关联,它仍会向数据库发出请求。它只会触发相关对象的验证。 回调after(:build)将在工厂建立后调用。
请注意,在大多数情况下,测试模型最好使用build_stubbed以获得更好的性能。在这里阅读更多信息: here

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接