Testing

Running Tests

composer test
# or
vendor/bin/phpunit

Test Structure

tests/
+-- Unit/
    +-- ContainerTest.php
    +-- DefinitionTest.php
    +-- AutowiringTest.php

Writing Tests

Testing Basic Resolution

public function testBindAndResolve(): void
{
    $container = new Container();
    $container->bind('foo', fn() => 'bar');

    $this->assertSame('bar', $container->get('foo'));
}

Testing Singletons

public function testSingletonReturnsSameInstance(): void
{
    $container = new Container();
    $container->singleton(stdClass::class, fn() => new stdClass());

    $a = $container->get(stdClass::class);
    $b = $container->get(stdClass::class);

    $this->assertSame($a, $b);
}

Testing Factory Bindings

public function testFactoryReturnsNewInstance(): void
{
    $container = new Container();
    $container->bind(stdClass::class, fn() => new stdClass());

    $a = $container->get(stdClass::class);
    $b = $container->get(stdClass::class);

    $this->assertNotSame($a, $b);
}

Testing Auto-wiring

class Dependency {}

class Consumer {
    public function __construct(public Dependency $dep) {}
}

public function testAutowiring(): void
{
    $container = new Container();
    $consumer = $container->get(Consumer::class);

    $this->assertInstanceOf(Consumer::class, $consumer);
    $this->assertInstanceOf(Dependency::class, $consumer->dep);
}

Testing Circular Dependency Detection

public function testCircularDependencyThrows(): void
{
    $container = new Container();
    $container->bind('a', fn($c) => $c->get('b'));
    $container->bind('b', fn($c) => $c->get('a'));

    $this->expectException(ContainerException::class);
    $this->expectExceptionMessage('Circular dependency');

    $container->get('a');
}

Testing Not Found

public function testNotFoundThrows(): void
{
    $container = new Container();

    $this->expectException(NotFoundException::class);
    $container->get('nonexistent');
}

Mocking Dependencies

public function testWithMockedDependency(): void
{
    $container = new Container();

    $mockLogger = $this->createMock(LoggerInterface::class);
    $mockLogger->expects($this->once())->method('info');

    $container->singleton(LoggerInterface::class, fn() => $mockLogger);

    $service = $container->get(MyService::class);
    $service->doSomething();
}