CaiWuXiTong/tests/Unit/EcommerceFinance/UpstreamDatabaseProbeTest.php

66 lines
3.0 KiB
PHP

<?php
namespace Tests\Unit\EcommerceFinance;
use Mockery;
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
use Modules\EcommerceFinance\Services\UpstreamDatabaseProbe;
use PDO;
use PDOException;
use PDOStatement;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
class UpstreamDatabaseProbeTest extends TestCase
{
use MockeryPHPUnitIntegration;
private function connection(): array
{
return ['host' => 'db.example.test', 'port' => 25432, 'database' => "test' database",
'username' => 'reader', 'password' => 'fixture-secret', 'connect_timeout' => 5, 'query_timeout' => 120];
}
public function test_postgres_uses_tls_read_only_timeout_and_one_select(): void
{
$statement = Mockery::mock(PDOStatement::class);
$statement->shouldReceive('fetchColumn')->once()->andReturn(1);
$statement->shouldReceive('closeCursor')->once();
$pdo = Mockery::mock(PDO::class);
$pdo->shouldReceive('query')->once()->with('SELECT 1')->andReturn($statement);
$probe = Mockery::mock(UpstreamDatabaseProbe::class)->makePartial()->shouldAllowMockingProtectedMethods();
$probe->shouldReceive('connect')->once()->withArgs(function ($dsn, $user, $password) {
$this->assertStringContainsString('sslmode=require', $dsn);
$this->assertStringContainsString('default_transaction_read_only=on', $dsn);
$this->assertStringContainsString('statement_timeout=15000', $dsn);
$this->assertStringContainsString("dbname='test\\' database'", $dsn);
$this->assertStringContainsString('connect_timeout=5', $dsn);
$this->assertStringNotContainsString('fixture-secret', $dsn);
return $user === 'reader' && $password === 'fixture-secret';
})->andReturn($pdo);
$probe->probe('pgsql', $this->connection(), '测试库');
}
public function test_driver_error_never_exposes_credentials(): void
{
$probe = Mockery::mock(UpstreamDatabaseProbe::class)->makePartial()->shouldAllowMockingProtectedMethods();
$probe->shouldReceive('connect')->once()->andThrow(new PDOException('fixture-secret private driver detail'));
try {
$probe->probe('pgsql', $this->connection(), '测试库');
$this->fail('Expected sanitized connection error');
} catch (ServiceUnavailableHttpException $exception) {
$this->assertStringContainsString('PostgreSQL 连接失败', $exception->getMessage());
$this->assertStringNotContainsString('fixture-secret', $exception->getMessage());
$this->assertNull($exception->getPrevious());
}
}
public function test_unsupported_driver_is_not_probed(): void
{
$this->expectException(ServiceUnavailableHttpException::class);
$this->expectExceptionMessage('不支持此数据库类型');
(new UpstreamDatabaseProbe())->probe('unknown', [], '测试库');
}
}