Ruf*_*eng 4 ruby rspec ruby-on-rails factory-bot
我有一个从 REST API 获取信息的对象。假设我从 API 调用 Posts,并且可以指定要提取的字段。仅举一个例子来说明它的外观:
Post.find!(id: 1, fields: [:id, :title, :description])
Run Code Online (Sandbox Code Playgroud)
这会执行 API 调用,并返回一个包含这些指定字段的 Post 对象。
为了进行测试,我使用 Factory Bot 对该 API 调用进行存根,并直接返回一个 Post 对象,其中包含它可以查询的所有可能字段。
这种方法不是最好的,因为测试总是返回所有字段和代码本身,也许我只需要几个字段而不是全部字段
所以我试图实现类似的目标(在 FactoryBot 中):
build(:post, fields: [:id,:title])
并设置一个仅包含 id 和 title 的 Post 对象。
如果我这样做build(:post, fields: [:title, :created_at])
并设置一个仅包含标题和created_at的Post对象。等等...
做了一些研究并尝试了一些想法,但关于如何构建这个流程的所有想法都失败了。
关于如何实现这种行为有什么想法吗?
EDIT
Traits 似乎是一个不错的选择,但我必须与 API 调用保持一致,指定这些fields
. 所以特质对我不起作用......
假设这是您的 Post 工厂:
FactoryBot.define do
factory :post do
sequence(:title) { |n| "Post no. #{n}" }
description 'Post description'
created_at { DateTime.now }
end
end
Run Code Online (Sandbox Code Playgroud)
当你调用它时build(:post)
,它将创建一个带有标题、created_at 和描述集的对象。
但是,如果您将从工厂中删除这些字段(或将它们移到特征下):
FactoryBot.define do
factory :post do
trait :all_fields do
sequence(:title) { |n| "Post no. #{n}" }
description 'Post description'
created_at { DateTime.now }
end
end
end
Run Code Online (Sandbox Code Playgroud)
然后:
build(:post, title: 'Post title', description: 'Post description')
将创建一个仅设置标题和描述的帖子对象(created_at将为nil)build(:post, :all_fields)
将创建一个 post 对象,并将设置所有字段。编辑
我想我现在更好地理解这个问题了。假设这是您的工厂:
FactoryBot.define do
factory :post do
sequence(:title) { |n| "Post no. #{n}" }
created_at { DateTime.now }
description 'Post description'
end
end
Run Code Online (Sandbox Code Playgroud)
将其更改为:
FactoryBot.define do
factory :post do
transient do
fields []
end
sequence(:title) { |n| "Post no. #{n}" }
created_at { DateTime.now }
description 'Post description'
after :build do |post, evaluator|
unless evaluator.fields.empty? do
(post.attributes.keys - evaluator.fields).each do |attribute_to_remove|
post.send("#{attribute_to_remove}=", nil)
end
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
然后,你可以这样调用它:
build(:post)
创建包含所有字段的帖子build(:post, fields: ['description', 'title'])
创建一个帖子,其中除描述和标题之外的所有内容都是nil
。这个解决方案应该按预期工作,但它可能会减慢你的测试速度(而且我认为它看起来不太好:))