Criar dados de teste manualmente é repetitivo e frágil. Se o modelo mudar (ex: um novo campo obrigatório), precisamos atualizar cada lugar que cria dados manualmente.
Com FactoryBot, definimos os dados de teste em um único lugar. Os cenários apenas pedem build(:user) e recebem um objeto pronto - sem se preocupar com os detalhes de cada campo.
O model define a estrutura dos dados. Neste projeto usamos Struct pela simplicidade:
# lib/models/users_model.rb
UsersModel = Struct.new(:nome, :email, :password, :administrador) do
def user_hash
to_h
end
endto_h converte o Struct em Hash com chaves Symbol, e user_hash expõe esse comportamento com um nome mais expressivo.
user = UsersModel.new('Ana', 'ana@example.com', 'senha123', 'false')
user.user_hash
# => { nome: "Ana", email: "ana@example.com", password: "senha123", administrador: "false" }Quando chamamos .to_json em seguida, as chaves Symbol são convertidas para String automaticamente:
user.user_hash.to_json
# => '{"nome":"Ana","email":"ana@example.com","password":"senha123","administrador":"false"}'A factory define como criar instâncias do model com dados gerados automaticamente:
# lib/factories/users_factory.rb
require 'faker'
require_relative '../models/users_model'
FactoryBot.define do
factory :user, class: UsersModel do
nome { Faker::Name.name }
email { Faker::Internet.email(domain: 'example.com') }
password { Faker::Internet.password(min_length: 6, max_length: 12, mix_case: true) }
administrador { 'false' }
end
endCada campo recebe um bloco { } que é avaliado na hora da criação - garantindo dados únicos e aleatórios a cada chamada.
O Faker gera dados falsos e realistas. Alguns exemplos úteis para testes de API:
Faker::Name.name # => "Carlos Silva"
Faker::Internet.email(domain: 'example.com') # => "carlos.silva@example.com"
Faker::Internet.password(min_length: 6) # => "sK9#mLp"
Faker::Internet.username # => "carlos_silva"
Faker::Number.number(digits: 5) # => "48291"
Faker::Lorem.sentence # => "Lorem ipsum dolor sit amet."Atenção:
Faker::Internet.emailsem argumentos gera TLDs reservados como.teste.example. A ServeRest (e muitas APIs) rejeita esses emails como inválidos. Sempre usedomain: 'example.com'ou similar.
O World(FactoryBot::Syntax::Methods) no env.rb injeta o método build diretamente nos steps:
# Cria o objeto sem salvar em banco (não tem banco, mas o nome vem dessa convenção)
user = build(:user)
# Acessa os campos
user.nome # => "Carlos Silva"
user.email # => "carlos.silva@example.com"
# Converte para Hash para enviar como corpo da requisição
user.user_hash
# => { nome: "Carlos Silva", email: "carlos.silva@example.com", ... }Dado('que existe um usuário cadastrado') do
@payload_user = build(:user).user_hash
response = users_service.post_user(@payload_user)
@created_user_id = response.parsed_response['_id']
endÉ possível sobrescrever qualquer campo da factory na hora da criação:
# Criar um usuário administrador
admin = build(:user, administrador: 'true')
# Criar com email fixo (útil para testar duplicata)
user = build(:user, email: 'fixo@example.com')build(:user)
└── FactoryBot executa o bloco de cada campo
├── nome: Faker::Name.name => "Ana Lima"
├── email: Faker::Internet.email... => "ana@example.com"
├── password: Faker::Internet.password => "Xk3#mP"
└── administrador: 'false'
└── Retorna UsersModel.new("Ana Lima", "ana@example.com", "Xk3#mP", "false")
.user_hash
└── Retorna { nome: "Ana Lima", email: "ana@example.com", ... }
.to_json
└── '{"nome":"Ana Lima","email":"ana@example.com",...}'