Skip to content

elciorodrigo/php-unit-test

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Microserviço de Conta Bancária

Microserviço em PHP demonstrando os princípios SOLID e testes unitários, desenvolvido com CodeIgniter 4 (PHP Spark). Este projeto utiliza armazenamento em memória (sem banco de dados) sendo ideal para aprendizado e demonstração de conceitos.

📋 Índice

📋 Pré-requisitos

  • PHP: 8.1 ou superior
  • Composer: Versão mais recente
  • Extensões PHP:
    • mbstring
    • json
    • xml
    • curl (para testes com curl)

🚀 Instalação

Passo 1: Instalar Dependências

No diretório do projeto, execute:

composer install

Isso instalará:

  • CodeIgniter 4 Framework
  • PHPUnit (para testes)

Passo 2: Verificar Permissões

Certifique-se de que o diretório writable tem permissões adequadas:

chmod -R 755 writable

▶️ Executando o Microserviço

Método 1: PHP Built-in Server (Recomendado)

php -S localhost:8080 -t public

O servidor estará disponível em: http://localhost:8080

Método 2: Usando PHP Spark

php spark serve

🧪 Executando os Testes

Executar Todos os Testes

composer test

Ou diretamente:

./vendor/bin/phpunit

Executar Testes Específicos

Teste da Entidade Account:

./vendor/bin/phpunit tests/Unit/Entities/AccountTest.php

Teste do Repository:

./vendor/bin/phpunit tests/Unit/Repositories/InMemoryAccountRepositoryTest.php

Teste do Service:

./vendor/bin/phpunit tests/Unit/Services/AccountServiceTest.php

Executar com Cobertura de Código

./vendor/bin/phpunit --coverage-html coverage

📚 Endpoints da API

1. Listar Todas as Contas

GET /api/accounts

Exemplo:

curl http://localhost:8080/api/accounts

Resposta:

[
  {
    "id": 1,
    "account_number": "12345-6",
    "holder_name": "João Silva",
    "balance": 1000.50,
    "account_type": "checking",
    "created_at": "2024-01-01 10:00:00",
    "updated_at": "2024-01-01 10:00:00"
  }
]

2. Buscar Conta por ID

GET /api/accounts/{id}

Exemplo:

curl http://localhost:8080/api/accounts/1

Resposta:

{
  "id": 1,
  "account_number": "12345-6",
  "holder_name": "João Silva",
  "balance": 1000.50,
  "account_type": "checking",
  "created_at": "2024-01-01 10:00:00",
  "updated_at": "2024-01-01 10:00:00"
}

3. Criar Nova Conta

POST /api/accounts

Exemplo:

curl -X POST http://localhost:8080/api/accounts \
  -H "Content-Type: application/json" \
  -d '{
    "account_number": "12345-6",
    "holder_name": "João Silva",
    "balance": 1000.50,
    "account_type": "checking"
  }'

Campos obrigatórios:

  • account_number (string)
  • holder_name (string)

Campos opcionais:

  • balance (float, padrão: 0.0)
  • account_type (string: "checking" ou "savings", padrão: "checking")

Resposta (201 Created):

{
  "id": 1,
  "account_number": "12345-6",
  "holder_name": "João Silva",
  "balance": 1000.50,
  "account_type": "checking",
  "created_at": "2024-01-01 10:00:00",
  "updated_at": null
}

4. Atualizar Conta

PUT /api/accounts/{id}

Exemplo:

curl -X PUT http://localhost:8080/api/accounts/1 \
  -H "Content-Type: application/json" \
  -d '{
    "holder_name": "João Silva Santos",
    "balance": 1500.00
  }'

Resposta (200 OK):

{
  "id": 1,
  "account_number": "12345-6",
  "holder_name": "João Silva Santos",
  "balance": 1500.00,
  "account_type": "checking",
  "created_at": "2024-01-01 10:00:00",
  "updated_at": "2024-01-01 11:00:00"
}

5. Deletar Conta

DELETE /api/accounts/{id}

Exemplo:

curl -X DELETE http://localhost:8080/api/accounts/1

Resposta (200 OK):

{
  "message": "Conta deletada com sucesso"
}

📖 Documentação Swagger

Acessar Interface Swagger

Abra no navegador:

http://localhost:8080/swagger

Acessar JSON do Swagger

http://localhost:8080/swagger.json

A interface Swagger permite:

  • Visualizar todos os endpoints
  • Testar requisições diretamente no navegador
  • Ver exemplos de requisições e respostas
  • Entender a estrutura dos dados

🏗️ Arquitetura e Princípios SOLID

Estrutura do Projeto

app/
├── Config/          # Configurações do CodeIgniter
├── Controllers/     # Controladores HTTP
├── Entities/        # Entidades de domínio (Account)
├── Repositories/    # Repositórios (In-Memory)
├── Services/        # Camada de serviços
└── Views/           # Views (Swagger)

tests/
└── Unit/            # Testes unitários
    ├── Entities/
    ├── Repositories/
    └── Services/

Princípios SOLID Aplicados

1. Single Responsibility Principle (SRP)

  • Cada classe tem uma única responsabilidade
  • Account: Responsável apenas por representar uma conta bancária
  • AccountService: Gerencia apenas as regras de negócio
  • InMemoryAccountRepository: Gerencia apenas o armazenamento
  • AccountController: Responsável apenas por receber requisições HTTP

2. Open/Closed Principle (OCP)

  • AccountRepositoryInterface: Permite extensão através de novas implementações (ex: DatabaseRepository) sem modificar o código existente
  • As classes estão abertas para extensão, fechadas para modificação

3. Liskov Substitution Principle (LSP)

  • Qualquer implementação de AccountRepositoryInterface pode substituir InMemoryAccountRepository sem quebrar o código

4. Interface Segregation Principle (ISP)

  • AccountRepositoryInterface contém apenas métodos essenciais para operações de conta
  • Interfaces específicas e focadas

5. Dependency Inversion Principle (DIP)

  • AccountService depende de AccountRepositoryInterface (abstração), não de implementações concretas
  • AccountController depende de AccountService (abstração)

🧪 Testes Unitários

Cobertura de Testes

  • AccountTest: 7 testes - Testa a entidade Account (depósito, saque, validações)
  • InMemoryAccountRepositoryTest: 8 testes - Testa operações CRUD do repositório
  • AccountServiceTest: 9 testes - Testa regras de negócio e validações
  • Total: 24 testes unitários

Exemplos de Testes

// Teste de depósito
$account = new Account(null, '12345-6', 'João Silva', 1000.0);
$account->deposit(500.0);
$this->assertEquals(1500.0, $account->getBalance());

// Teste de saque com saldo insuficiente
$account = new Account(null, '12345-6', 'João Silva', 1000.0);
$this->expectException(\RuntimeException::class);
$account->withdraw(2000.0);

📊 Estrutura de Dados

Account (Conta Bancária)

{
  "id": 1,
  "account_number": "12345-6",
  "holder_name": "João Silva",
  "balance": 1000.50,
  "account_type": "checking",
  "created_at": "2024-01-01 10:00:00",
  "updated_at": "2024-01-01 11:00:00"
}

Campos:

  • id: ID único da conta (gerado automaticamente)
  • account_number: Número da conta bancária
  • holder_name: Nome do titular da conta
  • balance: Saldo atual (float)
  • account_type: Tipo de conta ("checking" ou "savings")
  • created_at: Data de criação
  • updated_at: Data de última atualização

🔍 Validações e Regras de Negócio

Validações de Criação/Atualização

  • ✅ Número da conta é obrigatório
  • ✅ Nome do titular é obrigatório
  • ✅ Saldo não pode ser negativo
  • ✅ Tipo de conta deve ser "checking" ou "savings"

Regras de Negócio da Entidade

  • ✅ Depósito deve ser maior que zero
  • ✅ Saque deve ser maior que zero
  • ✅ Saque não pode exceder o saldo disponível

💾 Armazenamento

Este projeto utiliza armazenamento em memória (In-Memory) para fins didáticos. Os dados são perdidos quando o servidor é reiniciado.

Para produção, você pode criar uma nova implementação de AccountRepositoryInterface que utilize banco de dados.

📝 Exemplos de Uso

Fluxo Completo: Criar, Listar, Atualizar e Deletar

# 1. Criar conta
curl -X POST http://localhost:8080/api/accounts \
  -H "Content-Type: application/json" \
  -d '{"account_number": "12345-6", "holder_name": "João Silva", "balance": 1000.0}'

# 2. Listar todas as contas
curl http://localhost:8080/api/accounts

# 3. Buscar conta específica
curl http://localhost:8080/api/accounts/1

# 4. Atualizar conta
curl -X PUT http://localhost:8080/api/accounts/1 \
  -H "Content-Type: application/json" \
  -d '{"balance": 1500.0}'

# 5. Deletar conta
curl -X DELETE http://localhost:8080/api/accounts/1

Criar uma conta

curl -X POST http://localhost:8080/api/accounts \
  -H "Content-Type: application/json" \
  -d '{
    "account_number": "12345-6",
    "holder_name": "João Silva",
    "balance": 1000.50,
    "account_type": "checking"
  }'

Listar todas as contas

curl http://localhost:8080/api/accounts

Buscar conta por ID

curl http://localhost:8080/api/accounts/1

Atualizar conta

curl -X PUT http://localhost:8080/api/accounts/1 \
  -H "Content-Type: application/json" \
  -d '{
    "holder_name": "João Silva Santos",
    "balance": 1500.00
  }'

Deletar conta

curl -X DELETE http://localhost:8080/api/accounts/1

🔧 Troubleshooting

Problema: "Class not found"

Solução: Execute composer dump-autoload

Problema: "Permission denied" no writable

Solução: chmod -R 755 writable

Problema: Porta 8080 já em uso

Solução: Use outra porta: php -S localhost:8081 -t public

Problema: Testes não executam

Solução: Verifique se PHPUnit está instalado: composer install --dev

✅ Componentes Implementados

1. Estrutura Base

  • ✅ CodeIgniter 4 Framework
  • ✅ PHP 8.1+
  • ✅ Composer para gerenciamento de dependências
  • ✅ Estrutura de diretórios organizada

2. Entidades (Domain Layer)

  • Account.php - Entidade de Conta Bancária
    • Métodos: deposit(), withdraw()
    • Validações de negócio
    • Transformação para array

3. Repositórios (Data Layer)

  • AccountRepositoryInterface.php - Interface (abstração)
  • InMemoryAccountRepository.php - Implementação em memória
    • CRUD completo
    • Armazenamento temporário (sem banco de dados)

4. Serviços (Business Layer)

  • AccountService.php - Regras de negócio
    • Validações de dados
    • Orquestração de operações
    • Tratamento de erros

5. Controllers (Presentation Layer)

  • AccountController.php - CRUD RESTful
    • GET /api/accounts - Listar
    • GET /api/accounts/{id} - Buscar
    • POST /api/accounts - Criar
    • PUT /api/accounts/{id} - Atualizar
    • DELETE /api/accounts/{id} - Deletar
  • SwaggerController.php - Interface Swagger
  • SwaggerJsonController.php - JSON OpenAPI

6. Testes Unitários

  • AccountTest.php - Testes da entidade
    • Criação de conta
    • Depósito e saque
    • Validações
  • InMemoryAccountRepositoryTest.php - Testes do repositório
    • CRUD completo
    • Casos de erro
  • AccountServiceTest.php - Testes do serviço
    • Regras de negócio
    • Validações
    • Tratamento de erros

7. Documentação

  • ✅ Swagger/OpenAPI integrado
  • ✅ README.md completo

📦 Dependências

  • CodeIgniter 4: Framework PHP
  • PHPUnit: Framework de testes

🎯 Objetivos do Projeto

Este projeto foi desenvolvido para demonstrar:

  1. ✅ Aplicação dos princípios SOLID
  2. ✅ Arquitetura em camadas (Controller → Service → Repository)
  3. ✅ Testes unitários abrangentes
  4. ✅ Documentação Swagger/OpenAPI
  5. ✅ Padrões de design (Repository, Service)
  6. ✅ Injeção de dependências
  7. ✅ Separação de responsabilidades

⚠️ Observações Importantes

  1. Armazenamento em Memória: Os dados são perdidos quando o servidor é reiniciado
  2. Sem Banco de Dados: Este projeto é didático e não utiliza banco de dados
  3. Ambiente de Desenvolvimento: Configurado para desenvolvimento, não para produção

📄 Licença

Este é um projeto educacional para fins de demonstração.


Desenvolvido para fins educacionais e demonstração de conceitos SOLID e Testes Unitários em PHP

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published