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

168 lines
5.4 KiB
PHP

<?php
namespace Tests\Unit;
use PDO;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use Services\Database;
use Services\DataBase\Classes\PdoDriver;
use Services\DataBase\Classes\Profiler;
use System\Classes\Config;
use System\Classes\MyException;
use System\Classes\Repository;
class RepositoryTestItemRepository extends Repository
{
public function __construct(?string $connection = null)
{
parent::__construct('repository_test_items', connection: $connection);
}
}
class RepositoryTest extends TestCase
{
private PdoDriver $driver;
private RepositoryTestItemRepository $repository;
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 repository_test_items');
$this->driver->exec('CREATE TABLE repository_test_items (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), qty INT)');
$this->repository = new RepositoryTestItemRepository();
}
protected function tearDown(): void
{
Profiler::reset();
if (isset($this->driver)) {
try {
$this->driver->exec('DROP TABLE IF EXISTS repository_test_items');
} catch (MyException) {
}
}
// Database::instance() кэширует подключение статически — сбрасываем между тестами
$ref = new ReflectionClass(Database::class);
$prop = $ref->getProperty('_instances');
$prop->setAccessible(true);
$prop->setValue(null, []);
}
public function testCreateAndGet(): void
{
$id = $this->repository->create(['name' => 'foo', 'qty' => 3]);
$row = $this->repository->get($id);
$this->assertSame('foo', $row->name);
$this->assertSame(3, (int) $row->qty);
}
public function testGetMissingReturnsFalse(): void
{
$this->assertFalse($this->repository->get(999999));
}
public function testGetListWithWhere(): void
{
$this->repository->create(['name' => 'a', 'qty' => 1]);
$this->repository->create(['name' => 'b', 'qty' => 2]);
$this->repository->create(['name' => 'a', 'qty' => 5]);
$rows = $this->repository->getList('*', ['name' => 'a'], '', 'ASC', PDO::FETCH_ASSOC);
$this->assertCount(2, $rows);
}
public function testGetItemWhere(): void
{
$this->repository->create(['name' => 'foo', 'qty' => 1]);
$row = $this->repository->getItemWhere("name = 'foo'");
$this->assertSame('foo', $row->name);
}
public function testGetItemWhereEmptyReturnsNull(): void
{
$this->assertNull($this->repository->getItemWhere(''));
}
public function testUpdate(): void
{
$id = $this->repository->create(['name' => 'foo', 'qty' => 1]);
$affected = $this->repository->update(['id' => $id, 'qty' => 10]);
$this->assertSame(1, $affected);
$this->assertSame(10, (int) $this->repository->get($id)->qty);
}
public function testUpdateWithoutPrimaryKeyThrows(): void
{
$this->expectException(MyException::class);
$this->repository->update(['qty' => 10]);
}
public function testDelete(): void
{
$id = $this->repository->create(['name' => 'foo', 'qty' => 1]);
$this->assertTrue($this->repository->delete($id));
$this->assertFalse($this->repository->get($id));
}
public function testDeleteWhere(): void
{
$this->repository->create(['name' => 'a', 'qty' => 1]);
$this->repository->create(['name' => 'a', 'qty' => 2]);
$this->repository->create(['name' => 'b', 'qty' => 3]);
$this->repository->deleteWhere('name = ?', ['a']);
$this->assertCount(1, $this->repository->getList('*', [], '', 'ASC', PDO::FETCH_ASSOC));
}
public function testTransactionRollsBackOnException(): void
{
try {
$this->repository->transaction(function () {
$this->repository->create(['name' => 'should_rollback', 'qty' => 1]);
throw new \RuntimeException('boom');
});
$this->fail('Ожидалось RuntimeException');
} catch (\RuntimeException) {
}
$this->assertCount(0, $this->repository->getList('*', ['name' => 'should_rollback'], '', 'ASC', PDO::FETCH_ASSOC));
}
public function testGetListFetchAssoc(): void
{
$this->repository->create(['name' => 'foo', 'qty' => 1]);
$rows = $this->repository->getList('*', [], '', 'ASC', PDO::FETCH_ASSOC);
$this->assertIsArray($rows[0]);
$this->assertSame('foo', $rows[0]['name']);
}
public function testGetListDefaultFetchClassUsesObjClass(): void
{
// По умолчанию (без явного $fetch) getList() отдаёт $this->obj_class — не generic stdClass.
$this->repository->create(['name' => 'foo', 'qty' => 1]);
$rows = $this->repository->getList('*');
$this->assertInstanceOf(\Services\DataBase\Model::class, $rows[0]);
$this->assertSame('foo', $rows[0]->name);
}
}