Rails factory bot Document

创建: 2019/10/10

完成: 2019/10/10

更新: 2020/02/20 补充trait的用法

 

安装
 Gemfile  
# Gemfile
group :development, :test do
  gem 'factory_bot_rails'
end

 

 省略类名的设置

 

#spec/rails_helper.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

 

 文件位置

 

spec/factories/

 

   
使用
 定义factory

 

FactoryBot.define do
  factory :book do
    title { "factory sample" }
  end
  factory :sample, class: Book do
    title { "sample" }
  end
end

 

 生成数据

 

 方法  返回值  DB保存  DB保存(association)  id
 
build(factory[, attributes])

 attributes必须为存在的属性

 model实例  X  O  nil
 
build_stubbed(factory[, attributes])

 ● attributes必须为存在的属性

 model实例  X  X  合适的值
 
create(factory[, attributes])

 ● attributes必须为存在的属性

 model实例  O  O  DB保存的值
 
attributes_for(factory[, attributes])

 ● 只返回factory里指定的,没有指定的一律不返回

 ● attributes可以指定任意, 包括不存在的属性

 属性哈希  X  X  无

 

 批量生成

 

*_list(factory, count, attributes)

例:

books = create_list(:book, 10, price: 9999)

 

 序列

 sequence:

sequence :name do |i|
    ...
end

 generate:

factory :sample do
    attribute { generate :name }
end

 例: 

FactoryBot.define do
  sequence :isbn do |p|
    "UUID-#{11111*p}"
  end

  factory :book do
    title { "factory sample" }
    isbn { generate :isbn }
  end
end

 

 

 生成association

 (belongs_to)

 

association :关联名, factory: ...[, strategy: :build][, attributes]
 factory  如果与关联名相同则可以省略
 strategy

 生成使用的方法

 build/create/build_stubbed

 attributes

 指定覆盖的属性

 ● 只能用在belongs_to

 ● 也可以直接在belongs_to关系里放入factory  

FactoryBot.define do
  sequence :review_bodies do |i|
    "review-#{i}"
  end
  factory :review do
    body { generate :review_bodies }
    user
    book
  end
end

 

 

 给factory添加别名

 

factory :sample, class: User, aliases: [...] do
    ...
end

 

 使用固有词做属性

 

add_attribute(name) { ... }

 

 添加不是固有attribute的属性

 

transient do
    sample { "sample" }
    ...
end

例:

FactoryBot.define do
  sequence :review_bodies do |i|
    "review-#{i}"
  end
  factory :review do
    transient do
      comment { "" }
    end
    body { comment.blank? ? generate(:review_bodies) : comment }
    user
    book
  end
end

 

 继承

 嵌套即可

factory :book do
  title { "factory sample" }
  isbn { generate :isbn }
  factory :sample do
    title { "sample" }
  end
end

  ● 不嵌套则指定parent

factory :sample, parent: :book do
  title { "sample" }
end

 

 

 不继承而改变内容

 

FactoryGirl.modify do
  factory :alice do
    name 'Alex'
  end
end

 

 

 定义属性组合

 定义属性的组合, 可以用trait的组合来直接定义factory

 定义 

trait do
    attribute1 { 1 }
    attribute2 { 2 }
    ...
}

 ● 定义直接放在创建的方法里,则可以在创建时用参数指定

 使用

# 直接指定
factory :dummy, traits: [:trait1, :trait2]

# 内部指定
factory :dummy do
    trait1
    trait2
    ...
end

# 呼出时指定
create :dummy, :trait1
create :dummy, traits: [:trait1, :trait2, ...] # 指定多个

 例:

FactoryBot.define do
  sequence :isbn do |p|
    "UUID-#{11111*p}"
  end
  trait :book_attr do
    title { "factory sample" }
    isbn { generate :isbn }
  end
  factory :book do
    book_attr
    factory :sample do
      title { "sample" }
    end
  end
  # factory :sample, parent: :book do
  #   title { "sample" }
  # end
end

 

 

 callback 

 

after(:build) do |record|
    ...
end

 

 callback  时间节点  对应处理
 before(:create)  factorydb保存前  create
 after(:create)  factorydb保存后  create
 after(:build)  factory build后  create, build
 after(:stub)  生成stub后  build_stubbed

 ● 定义多个不会覆盖,而是按顺序执行

 

   
   
posted @ 2019-10-10 14:20  懒虫哥哥  阅读(483)  评论(0编辑  收藏  举报