API

Testes de Factories - AgrSis

Testes de Factories - AgrSis

Como Testar as Factories

1. Via Tinker (Recomendado)

# Iniciar container
docker-compose up -d

# Acessar Tinker
docker exec -it agrsis_api php artisan tinker

Testes Básicos:

// 1. Testar UserFactory
$user = User::factory()->create();
echo "User ID: {$user->id}, Nome: {$user->name}, Email: {$user->email}\n";

// 2. Testar CustomerFactory PF
$customerPF = Customer::factory()->pf()->create();
echo "Cliente PF: {$customerPF->nome}, CPF: {$customerPF->cpf_cnpj}\n";

// 3. Testar CustomerFactory PJ
$customerPJ = Customer::factory()->pj()->create();
echo "Cliente PJ: {$customerPJ->nome}, CNPJ: {$customerPJ->cpf_cnpj}\n";

// 4. Testar SupplierFactory
$supplier = Supplier::factory()->create();
echo "Fornecedor: {$supplier->nome}, CNPJ: {$supplier->cnpj}\n";

// 5. Testar ProductFactory
$product = Product::factory()->create();
echo "Produto: {$product->descricao}\n";

// 6. Testar OrderFactory
$order = Order::factory()->create();
echo "Pedido ID: {$order->id}, Cliente: {$order->customer->nome}\n";

// 7. Testar SubscriptionPlanFactory
$plan = SubscriptionPlan::factory()->basic()->create();
echo "Plano: {$plan->nome}, Valor: R$ {$plan->valor_mensal}\n";

// 8. Testar TransactionFactory
$transaction = Transaction::factory()->entrada()->create();
echo "Transação: {$transaction->descricao}, Valor: R$ {$transaction->valor}\n";

// 9. Testar múltiplos registros
$users = User::factory()->count(5)->create();
echo "Criados {$users->count()} usuários\n";

// 10. Testar States combinados
$userInativo = User::factory()->produtor()->inactive()->create();
echo "User inativo: {$userInativo->name}, Status: " . ($userInativo->status ? 'Ativo' : 'Inativo') . "\n";

2. Via Testes Automatizados

Criar arquivo: tests/Unit/FactoryTest.php

<?php

namespace Tests\Unit;

use Tests\TestCase;
use App\Models\User;
use App\Models\Customer;
use App\Models\Supplier;
use App\Models\Product;
use App\Models\Order;
use App\Models\SubscriptionPlan;
use App\Models\Transaction;
use Illuminate\Foundation\Testing\RefreshDatabase;

class FactoryTest extends TestCase
{
    use RefreshDatabase;

    public function test_user_factory(): void
    {
        $user = User::factory()->create();

        $this->assertDatabaseHas('users', [
            'id' => $user->id,
            'email' => $user->email,
        ]);
    }

    public function test_user_factory_admin_state(): void
    {
        $user = User::factory()->admin()->create();

        $this->assertEquals('admin', $user->perfil);
        $this->assertTrue($user->status);
    }

    public function test_customer_factory_pf(): void
    {
        $customer = Customer::factory()->pf()->create();

        $this->assertEquals(1, $customer->tipo); // TIPO_PESSOA_FISICA
        $this->assertNotNull($customer->cpf_cnpj);
        $this->assertEquals(11, strlen(preg_replace('/\D/', '', $customer->cpf_cnpj)));
    }

    public function test_customer_factory_pj(): void
    {
        $customer = Customer::factory()->pj()->create();

        $this->assertEquals(2, $customer->tipo); // TIPO_PESSOA_JURIDICA
        $this->assertNotNull($customer->cpf_cnpj);
        $this->assertEquals(14, strlen(preg_replace('/\D/', '', $customer->cpf_cnpj)));
    }

    public function test_supplier_factory(): void
    {
        $supplier = Supplier::factory()->create();

        $this->assertDatabaseHas('suppliers', [
            'id' => $supplier->id,
            'cnpj' => $supplier->cnpj,
        ]);
    }

    public function test_product_factory_creates_product_type(): void
    {
        $product = Product::factory()->create();

        $this->assertNotNull($product->productType);
        $this->assertNotNull($product->product_type_id);
    }

    public function test_order_factory_creates_customer(): void
    {
        $order = Order::factory()->create();

        $this->assertNotNull($order->customer);
        $this->assertNotNull($order->customer_id);
    }

    public function test_subscription_plan_basic_state(): void
    {
        $plan = SubscriptionPlan::factory()->basic()->create();

        $this->assertEquals('Básico', $plan->nome);
        $this->assertEquals(99.90, $plan->valor_mensal);
        $this->assertEquals(10, $plan->limite_pedidos);
    }

    public function test_subscription_plan_premium_state(): void
    {
        $plan = SubscriptionPlan::factory()->premium()->create();

        $this->assertEquals('Premium', $plan->nome);
        $this->assertEquals(599.90, $plan->valor_mensal);
        $this->assertNull($plan->limite_pedidos); // ilimitado
    }

    public function test_transaction_factory_entrada(): void
    {
        $transaction = Transaction::factory()->entrada()->create();

        $this->assertEquals('entrada', $transaction->tipo);
    }

    public function test_transaction_factory_saida(): void
    {
        $transaction = Transaction::factory()->saida()->create();

        $this->assertEquals('saida', $transaction->tipo);
    }

    public function test_multiple_factories(): void
    {
        $users = User::factory()->count(10)->create();

        $this->assertEquals(10, $users->count());
        $this->assertDatabaseCount('users', 10);
    }

    public function test_factory_with_custom_attributes(): void
    {
        $user = User::factory()->create([
            'email' => 'teste@agrsis.com',
            'name' => 'Usuário Teste',
        ]);

        $this->assertEquals('teste@agrsis.com', $user->email);
        $this->assertEquals('Usuário Teste', $user->name);
    }

    public function test_inactive_state(): void
    {
        $user = User::factory()->inactive()->create();

        $this->assertFalse($user->status);
    }

    public function test_combined_states(): void
    {
        $user = User::factory()->produtor()->inactive()->create();

        $this->assertEquals('produtor', $user->perfil);
        $this->assertFalse($user->status);
    }
}

Rodar os testes:

# Todos os testes
php artisan test

# Com Docker
docker exec agrsis_api php artisan test

# Apenas testes de Factory
php artisan test --filter FactoryTest

# Com coverage
php artisan test --coverage

Criar arquivo: database/seeders/TestDataSeeder.php

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Customer;
use App\Models\Supplier;
use App\Models\Product;
use App\Models\ProductType;
use App\Models\Brand;
use App\Models\Order;
use App\Models\SubscriptionPlan;
use App\Models\State;
use App\Models\AccessType;

class TestDataSeeder extends Seeder
{
    public function run(): void
    {
        $this->command->info('Criando tipos de acesso...');
        AccessType::factory()->cliente()->create();
        AccessType::factory()->fornecedor()->create();
        AccessType::factory()->administrador()->create();

        $this->command->info('Criando usuários...');
        User::factory()->admin()->create(['email' => 'admin@agrsis.com']);
        User::factory()->produtor()->count(10)->create();
        User::factory()->fornecedor()->count(5)->create();

        $this->command->info('Criando clientes...');
        Customer::factory()->pf()->count(20)->create();
        Customer::factory()->pj()->count(10)->create();

        $this->command->info('Criando fornecedores...');
        Supplier::factory()->count(15)->create();
        Supplier::factory()->withSite()->count(5)->create();

        $this->command->info('Criando tipos de produtos e marcas...');
        ProductType::factory()->count(8)->create();
        Brand::factory()->count(10)->create();

        $this->command->info('Criando produtos...');
        Product::factory()->count(50)->create();

        $this->command->info('Criando pedidos...');
        Order::factory()->count(30)->create();
        Order::factory()->urgent()->count(5)->create();

        $this->command->info('Criando planos de assinatura...');
        SubscriptionPlan::factory()->basic()->create();
        SubscriptionPlan::factory()->professional()->create();
        SubscriptionPlan::factory()->premium()->create();

        $this->command->info('Criando estados...');
        State::factory()->count(27)->create();

        $this->command->info('Dados de teste criados com sucesso!');
    }
}

Rodar o seeder:

# Resetar banco e popular
php artisan migrate:fresh --seed --seeder=TestDataSeeder

# Com Docker
docker exec agrsis_api php artisan migrate:fresh --seed --seeder=TestDataSeeder

Resultados Esperados

UserFactory

  • ✅ CPF válido gerado
  • ✅ Email único
  • ✅ Senha hasheada
  • ✅ Celular no formato brasileiro
  • ✅ States funcionando (admin, produtor, fornecedor, inactive)

CustomerFactory

  • ✅ PF: CPF com 11 dígitos
  • ✅ PJ: CNPJ com 14 dígitos
  • ✅ Nome/Razão Social adequados ao tipo
  • ✅ Data de nascimento apenas para PF
  • ✅ Email e telefone únicos

SupplierFactory

  • ✅ CNPJ válido
  • ✅ Nome da empresa
  • ✅ Email corporativo
  • ✅ Site opcional
  • ✅ Status ativo por padrão

ProductFactory

  • ✅ Cria ProductType automaticamente
  • ✅ Descrição do produto gerada
  • ✅ Status ativo por padrão

OrderFactory

  • ✅ Cria Customer automaticamente
  • ✅ Data limite de cotação futura
  • ✅ Raio de fornecimento definido
  • ✅ States funcionando (urgent, rejected, inactive)

SubscriptionPlanFactory

  • ✅ States específicos (basic, professional, premium)
  • ✅ Valores corretos por plano
  • ✅ Limites configurados
  • ✅ Recursos em JSON

TransactionFactory

  • ✅ Valores financeiros corretos
  • ✅ States de tipo (entrada, saida)
  • ✅ States de status (pending, approved, rejected)
  • ✅ Data de transação gerada

Problemas Comuns

1. Erro "Class 'Database\Factories\xxxFactory' not found"

Solução:

composer dump-autoload
php artisan optimize:clear

2. Erro de validação CPF/CNPJ

Causa: Faker pode gerar CPF/CNPJ com formato mas sem validação de dígitos.

Solução: Use bibliotecas específicas ou configure o Faker corretamente.

3. Erro de relacionamento

Causa: Tentar criar relacionamento sem a foreign key.

Solução: Use o factory que cria automaticamente:

// ❌ Errado
$order = Order::factory()->create(['customer_id' => 999]);

// ✅ Correto
$order = Order::factory()->create(); // Cria customer automaticamente

// ✅ Ou
$customer = Customer::factory()->create();
$order = Order::factory()->create(['customer_id' => $customer->id]);

Checklist de Validação

  • UserFactory cria usuários válidos
  • CustomerFactory diferencia PF e PJ
  • SupplierFactory gera CNPJ válido
  • ProductFactory cria ProductType relacionado
  • OrderFactory cria Customer relacionado
  • SubscriptionPlanFactory com states corretos
  • TransactionFactory com tipos e status
  • States combinados funcionam
  • Multiple factories (count) funcionam
  • Atributos customizados funcionam

Próximos Passos

  1. Rodar testes automatizados
  2. Popular banco de desenvolvimento
  3. Validar dados gerados
  4. Criar factories adicionais conforme necessidade
  5. Implementar testes de integração

Criado em: 2025-12-04 Versão: 1.0

Copyright © 2026