createMock(TenantRegistry::class); $registry->expects(self::once()) ->method('getConfig') ->with(self::callback(static fn (TenantId $tenantId): bool => (string) $tenantId === 'a1b2c3d4-e5f6-7890-abcd-ef1234567890')) ->willReturn($tenantConfig); $databaseSwitcher = $this->createMock(TenantDatabaseSwitcher::class); $databaseSwitcher->expects(self::once()) ->method('currentDatabaseUrl') ->willReturn('postgresql://tenant:secret@db:5432/classeo_tenant_previous?serverVersion=18&charset=utf8'); $databaseSwitcher->expects(self::exactly(2)) ->method('useTenantDatabase') ->with( self::logicalOr( self::equalTo($tenantConfig->databaseUrl), self::equalTo('postgresql://tenant:secret@db:5432/classeo_tenant_previous?serverVersion=18&charset=utf8'), ), ); $middleware = new TenantDatabaseMiddleware( $registry, $databaseSwitcher, new TenantMessageTenantIdResolver(), ); $envelope = new Envelope($message); $result = $middleware->handle($envelope, new TestStack( new class implements MiddlewareInterface { public function handle(Envelope $envelope, StackInterface $stack): Envelope { return $envelope; } }, )); self::assertSame($envelope, $result); } #[Test] public function itLeavesTheCurrentConnectionUntouchedWhenTheMessageHasNoTenantId(): void { $registry = $this->createMock(TenantRegistry::class); $registry->expects(self::never())->method('getConfig'); $databaseSwitcher = $this->createMock(TenantDatabaseSwitcher::class); $databaseSwitcher->expects(self::never())->method('currentDatabaseUrl'); $databaseSwitcher->expects(self::never())->method('useTenantDatabase'); $databaseSwitcher->expects(self::never())->method('useDefaultDatabase'); $middleware = new TenantDatabaseMiddleware( $registry, $databaseSwitcher, new TenantMessageTenantIdResolver(), ); $message = new readonly class('batch-1') { public function __construct( public string $batchId, ) { } }; $envelope = new Envelope($message); $result = $middleware->handle($envelope, new TestStack( new class implements MiddlewareInterface { public function handle(Envelope $envelope, StackInterface $stack): Envelope { return $envelope; } }, )); self::assertSame($envelope, $result); } } final readonly class TestStack implements StackInterface { public function __construct( private MiddlewareInterface $next, ) { } public function next(): MiddlewareInterface { return $this->next; } }