BDD中有一部分我真的很困惑。我有各种不同的请求规格要测试。具有以下结构:
我对如何使用FactoryGirl建立工厂感到困惑。我熟悉关联和特征的概念。我熟悉build
和create
的概念。但我不确定在什么情况下使用这些。
我能说出我最困惑的最好的方法就是举一些例子。
我有一个请求规范来测试User
注册。出于显而易见的原因,我不在这里使用工厂。我理解这一点。
我有一个请求规范来测试创建新User
的{{1}}。我Products
是一个用户工厂。我假设我需要在这里使用create
而不是create
,因为build
中的CRUD方法会对通过URL传递的ID执行AR ProductsController
。如果我在这里错了,请纠正我。
我有一个请求规范来测试为find
添加不同的PriceLevels
。我在这里使用两个工厂:Product
和User
。
我有一个请求规范,用于测试为Product
的{{1}} Prices
添加不同的User
。现在我最多有3家工厂:Product
,PriceLevel
,User
。
现在如果Product
的{{1}}有PriceLevel
之类的内容怎么办?工厂失控。
当我到Price
时,我会说我想要一个让我一次创建整个结构的工厂。然而,我不想每次都创建整个结构 。此外,这些工厂可以自下而上或自上而下创建。
哪种方式更好,自下而上或自上而下?我可以创建干燥代码,让我可以选择单个工厂或立即创建整个shebang吗?我可以将has_and_belongs_to_many
块包裹在特征中吗?我是否会在请求规范中使用Currency
vs PriceLevel
?
非常感谢您的关注!
答案 0 :(得分:1)
首先,请求规范中的build
与create
:
我通常在控制器规范中使用build
或build_stubbed
,通过存根Model.find
来返回构建的实例。但是,在功能或请求规范中应该避免使用模拟,因此请继续create
这里的事情。
现在主要问题是:
这听起来像是特质的完美案例。通常,基础工厂应该只具有制作有效模型所需的属性。然后可以使用特征为常见或冗长的场景制作方便的“别名”。
您可以使用before(:create)
构建和分配相关模型。当FG最终在内部调用save
/ create
时,Rails将处理将所有内容保存在一起。
示例:
factory :user do
# ...
trait :with_products do
before(:create) do |user|
user.products = build_list(:product, 3)
end
end
trait :with_priced_products do
before(:create) do |user|
user.products = build_list(:product, 3, :with_prices)
end
end
end
factory :product do
# ...
trait :with_prices do
before(:create) do |product|
product.prices = build_list(:price, 3)
end
end
end
factory :price
如果您想自定义在构建时添加多少产品/价格,您只需添加ignore
d个属性,并通过前挂钩的双参数形式使用它们。
ignore do
number_of_products 3
end
before(:create) do |user, evaluator|
user.products = build_list(product, evaluator.number_of_products)
end
如果您希望能够在with_
或build
方案中使用这些build_stubbed
特征,则必须在每种情况下使用正确的策略复制相关的钩子。目前还没有简单的方法可以说“使用与模型相同的策略添加一些关系”,尽管这也是我自己的愿望清单项目。