Files
roi-theme/tests/Unit/Infrastructure/DI/DIContainerTest.php
FrankZamora de5fff4f5c Fase 1: Estructura Base y DI Container - Clean Architecture
COMPLETADO: Fase 1 de la migración a Clean Architecture + POO

## Estructura de Carpetas
- ✓ Estructura completa de 4 capas (Domain, Application, Infrastructure, Presentation)
- ✓ Carpetas de Use Cases (SaveComponent, GetComponent, DeleteComponent, SyncSchema)
- ✓ Estructura de tests (Unit, Integration, E2E)
- ✓ Carpetas de schemas y templates

## Composer y Autoloading
- ✓ PSR-4 autoloading configurado para ROITheme namespace
- ✓ Autoloader optimizado regenerado

## DI Container
- ✓ DIContainer implementado con patrón Singleton
- ✓ Métodos set(), get(), has() para gestión de servicios
- ✓ Getters específicos para ComponentRepository, ValidationService, CacheService
- ✓ Placeholders que serán implementados en Fase 5
- ✓ Prevención de clonación y deserialización

## Interfaces
- ✓ ComponentRepositoryInterface (Domain)
- ✓ ValidationServiceInterface (Application)
- ✓ CacheServiceInterface (Application)
- ✓ Component entity placeholder (Domain)

## Bootstrap
- ✓ functions.php actualizado con carga de Composer autoloader
- ✓ Inicialización del DIContainer
- ✓ Helper function roi_container() disponible globalmente

## Tests
- ✓ 10 tests unitarios para DIContainer (100% cobertura)
- ✓ Total: 13 tests unitarios, 28 assertions
- ✓ Suite de tests pasando correctamente

## Validación
- ✓ Script de validación automatizado (48/48 checks pasados)
- ✓ 100% de validaciones exitosas

La arquitectura base está lista para la Fase 2.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 13:48:24 -06:00

176 lines
4.8 KiB
PHP

<?php
declare(strict_types=1);
namespace ROITheme\Tests\Unit\Infrastructure\DI;
use PHPUnit\Framework\TestCase;
use ROITheme\Infrastructure\DI\DIContainer;
use RuntimeException;
use Exception;
/**
* DI Container Test
*
* Tests for the Dependency Injection Container.
*
* @package ROITheme\Tests\Unit\Infrastructure\DI
*/
class DIContainerTest extends TestCase
{
protected function setUp(): void
{
// Reset container before each test
DIContainer::reset();
}
protected function tearDown(): void
{
// Reset container after each test
DIContainer::reset();
}
/**
* @test
*/
public function it_should_return_singleton_instance(): void
{
$instance1 = DIContainer::getInstance();
$instance2 = DIContainer::getInstance();
$this->assertSame($instance1, $instance2, 'getInstance() should return the same instance');
}
/**
* @test
*/
public function it_should_prevent_cloning(): void
{
$this->expectError();
$this->expectErrorMessage('Call to private');
$container = DIContainer::getInstance();
$clone = clone $container; // This should trigger an error
}
/**
* @test
*/
public function it_should_prevent_unserialization(): void
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('Cannot unserialize singleton');
$container = DIContainer::getInstance();
$serialized = serialize($container);
unserialize($serialized);
}
/**
* @test
*/
public function it_should_register_and_retrieve_service(): void
{
$container = DIContainer::getInstance();
$service = new \stdClass();
$service->name = 'Test Service';
$container->set('test_service', $service);
$this->assertTrue($container->has('test_service'), 'Container should have the registered service');
$this->assertSame($service, $container->get('test_service'), 'Should retrieve the same service instance');
}
/**
* @test
*/
public function it_should_return_null_for_non_existent_service(): void
{
$container = DIContainer::getInstance();
$this->assertFalse($container->has('non_existent'), 'Container should not have non-existent service');
$this->assertNull($container->get('non_existent'), 'Should return null for non-existent service');
}
/**
* @test
*/
public function it_should_throw_exception_for_unimplemented_component_repository(): void
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('ComponentRepository not implemented yet');
$container = DIContainer::getInstance();
$container->getComponentRepository();
}
/**
* @test
*/
public function it_should_throw_exception_for_unimplemented_validation_service(): void
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('ValidationService not implemented yet');
$container = DIContainer::getInstance();
$container->getValidationService();
}
/**
* @test
*/
public function it_should_throw_exception_for_unimplemented_cache_service(): void
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('CacheService not implemented yet');
$container = DIContainer::getInstance();
$container->getCacheService();
}
/**
* @test
*/
public function it_should_reset_singleton_instance(): void
{
$instance1 = DIContainer::getInstance();
$instance1->set('test', new \stdClass());
DIContainer::reset();
$instance2 = DIContainer::getInstance();
$this->assertNotSame($instance1, $instance2, 'Reset should create a new instance');
$this->assertFalse($instance2->has('test'), 'New instance should not have old services');
}
/**
* @test
*/
public function it_should_manage_multiple_services(): void
{
$container = DIContainer::getInstance();
$service1 = new \stdClass();
$service1->name = 'Service 1';
$service2 = new \stdClass();
$service2->name = 'Service 2';
$service3 = new \stdClass();
$service3->name = 'Service 3';
$container->set('service1', $service1);
$container->set('service2', $service2);
$container->set('service3', $service3);
$this->assertTrue($container->has('service1'));
$this->assertTrue($container->has('service2'));
$this->assertTrue($container->has('service3'));
$this->assertSame($service1, $container->get('service1'));
$this->assertSame($service2, $container->get('service2'));
$this->assertSame($service3, $container->get('service3'));
}
}