Bicycle/tests/Unit/PdoDriverTest.php
Egor Isaev 9ff9cc54e6 dev
2026-08-07 12:34:27 +03:00

146 lines
5.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
use Services\DataBase\Classes\PdoDriver;
use Services\DataBase\Classes\Profiler;
use System\Classes\Config;
use System\Classes\MyException;
class PdoDriverTest extends TestCase
{
private PdoDriver $driver;
protected function setUp(): void
{
$config = Config::get('db', 'default')['connection'] ?? [];
$this->driver = new PdoDriver($config);
try {
$this->driver->pdo();
} catch (MyException $e) {
$this->markTestSkipped('Нет живого подключения к MariaDB (заполните App/config/config.local.php): ' . $e->getMessage());
}
$this->driver->exec('DROP TABLE IF EXISTS pdo_driver_test');
$this->driver->exec('CREATE TABLE pdo_driver_test (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255))');
}
protected function tearDown(): void
{
Profiler::reset();
if (isset($this->driver)) {
try {
$this->driver->exec('DROP TABLE IF EXISTS pdo_driver_test');
} catch (MyException) {
// соединения не было — нечего дропать
}
}
}
public function testFailoverThrowsWithAllHostErrors(): void
{
// Чисто логика failover — не требует живой БД, оба хоста заведомо недоступны
$driver = new PdoDriver(['hosts' => ['bad-host-1', 'bad-host-2'], 'dbname' => 'x', 'user' => 'x', 'password' => 'x']);
try {
$driver->pdo();
$this->fail('Ожидалось MyException');
} catch (MyException $e) {
$this->assertStringContainsString('bad-host-1', $e->getMessage());
$this->assertStringContainsString('bad-host-2', $e->getMessage());
}
}
public function testQueryInsertsAndSelects(): void
{
$this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['foo']);
$row = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['foo'])->fetch();
$this->assertSame('foo', $row['name']);
}
public function testLastInsertId(): void
{
$this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['foo']);
$this->assertNotFalse($this->driver->lastInsertId());
}
public function testCommitPersistsChanges(): void
{
$this->driver->beginTransaction();
$this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['committed']);
$this->driver->commit();
$row = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['committed'])->fetch();
$this->assertNotFalse($row);
}
public function testRollbackDiscardsChanges(): void
{
$this->driver->beginTransaction();
$this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['rolled_back']);
$this->driver->rollback();
$row = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['rolled_back'])->fetch();
$this->assertFalse($row);
}
public function testNestedTransactionRollbackDoesNotAffectOuter(): void
{
$this->driver->beginTransaction();
$this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['outer']);
$this->driver->beginTransaction(); // SAVEPOINT sp_1
$this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['inner']);
$this->driver->rollback(); // ROLLBACK TO SAVEPOINT sp_1 — не трогает 'outer'
$this->driver->commit(); // фиксирует внешнюю транзакцию
$outer = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['outer'])->fetch();
$inner = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['inner'])->fetch();
$this->assertNotFalse($outer);
$this->assertFalse($inner);
}
public function testTransactionHelperRollsBackOnException(): void
{
try {
$this->driver->transaction(function (PdoDriver $driver) {
$driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['should_rollback']);
throw new \RuntimeException('boom');
});
$this->fail('Ожидалось RuntimeException');
} catch (\RuntimeException) {
// ожидаемо
}
$row = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['should_rollback'])->fetch();
$this->assertFalse($row);
}
public function testManualPrepareExecuteIsProfiledToo(): void
{
// Регрессия: профилирование должно ловить любой execute(), а не только PdoDriver::query() —
// Repository сам делает $this->pdo->prepare()->execute() напрямую (см. get()/create()/...).
Profiler::reset();
$stmt = $this->driver->prepare('INSERT INTO pdo_driver_test (name) VALUES (?)');
$stmt->execute(['foo']);
$this->assertSame(1, Profiler::count());
}
public function testInTransaction(): void
{
$this->assertFalse($this->driver->inTransaction());
$this->driver->beginTransaction();
$this->assertTrue($this->driver->inTransaction());
$this->driver->commit();
$this->assertFalse($this->driver->inTransaction());
}
}