diff --git a/Tests/AbstractDatabaseDriverTestCase.php b/Tests/AbstractDatabaseDriverTestCase.php index b4377cf7..6c2c69fd 100644 --- a/Tests/AbstractDatabaseDriverTestCase.php +++ b/Tests/AbstractDatabaseDriverTestCase.php @@ -14,6 +14,7 @@ use Joomla\Database\QueryInterface; use Joomla\Test\DatabaseTestCase; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\TestDox; /** * Base test class for Joomla\Database\DatabaseDriver @@ -59,9 +60,7 @@ protected function loadExampleData(): void } } - /** - * @testdox The connection can be checked for encryption support - */ + #[TestDox('The connection can be checked for encryption support')] public function testIsConnectionEncryptionSupported() { $this->assertTrue( @@ -85,12 +84,11 @@ public static function dataDropTable(): array } /** - * @testdox A database table can be dropped - * * @param string $table The name of the database table to drop. * @param boolean $alreadyExists Flag indicating the table should exist before the DROP TABLE query. */ #[DataProvider('dataDropTable')] + #[TestDox('A database table can be dropped')] public function testDropTable(string $table, bool $alreadyExists) { $this->assertSame( @@ -117,13 +115,12 @@ public function testDropTable(string $table, bool $alreadyExists) abstract public static function dataEscape(): array; /** - * @testdox Text can be escaped - * * @param string $text The string to be escaped. * @param boolean $extra Optional parameter to provide extra escaping. * @param string $expected The expected result. */ #[DataProvider('dataEscape')] + #[TestDox('Text can be escaped')] public function testEscape($text, $extra, $expected) { $this->assertSame( @@ -132,9 +129,7 @@ public function testEscape($text, $extra, $expected) ); } - /** - * @testdox Values can be escaped in a locale aware context - */ + #[TestDox('Values can be escaped in a locale aware context')] public function testEscapeNonLocaleAware() { $origin = setlocale(LC_NUMERIC, 0); @@ -153,9 +148,7 @@ public function testEscapeNonLocaleAware() setlocale(LC_NUMERIC, $origin); } - /** - * @testdox The number of executed SQL statements can be retrieved - */ + #[TestDox('The number of executed SQL statements can be retrieved')] public function testGetCount() { $this->assertTrue( @@ -164,9 +157,7 @@ public function testGetCount() ); } - /** - * @testdox A PHP DateTime compatible date format for the database driver can be retrieved - */ + #[TestDox('A PHP DateTime compatible date format for the database driver can be retrieved')] public function testGetDateFormat() { $this->assertSame( @@ -175,9 +166,7 @@ public function testGetDateFormat() ); } - /** - * @testdox The minimum supported database version is retrieved - */ + #[TestDox('The minimum supported database version is retrieved')] public function testGetMinimum() { $this->assertTrue( @@ -186,9 +175,7 @@ public function testGetMinimum() ); } - /** - * @testdox The number of rows returned by the query can be retrieved - */ + #[TestDox('The number of rows returned by the query can be retrieved')] public function testGetNumRows() { $this->loadExampleData(); @@ -205,9 +192,7 @@ public function testGetNumRows() $this->assertSame(1, static::$connection->getNumRows()); } - /** - * @testdox A cached query instance can be retrieved - */ + #[TestDox('A cached query instance can be retrieved')] public function testGetQueryCachedQuery() { $query = static::$connection->createQuery() @@ -219,9 +204,7 @@ public function testGetQueryCachedQuery() $this->assertSame($query, static::$connection->getQuery(false)); } - /** - * @testdox An iterator for the database driver can be created - */ + #[TestDox('An iterator for the database driver can be created')] public function testGetIterator() { $this->loadExampleData(); @@ -246,13 +229,12 @@ public function testGetIterator() abstract public static function dataGetTableColumns(): array; /** - * @testdox Information about the columns of a database table is returned - * * @param string $table The name of the database table. * @param boolean $typeOnly True (default) to only return field types. * @param array $expected Expected result. */ #[DataProvider('dataGetTableColumns')] + #[TestDox('Information about the columns of a database table is returned')] public function testGetTableColumns(string $table, bool $typeOnly, array $expected) { $this->assertEquals( @@ -261,9 +243,7 @@ public function testGetTableColumns(string $table, bool $typeOnly, array $expect ); } - /** - * @testdox The list of tables is returned - */ + #[TestDox('The list of tables is returned')] public function testGetTableList() { $this->assertSame( @@ -274,9 +254,7 @@ public function testGetTableList() ); } - /** - * @testdox The database version is returned - */ + #[TestDox('The database version is returned')] public function testGetVersion() { $this->assertNotEmpty( @@ -284,9 +262,7 @@ public function testGetVersion() ); } - /** - * @testdox The connection can be checked for UTF support - */ + #[TestDox('The connection can be checked for UTF support')] public function testHasUtfSupport() { $this->assertTrue( @@ -294,9 +270,7 @@ public function testHasUtfSupport() ); } - /** - * @testdox An object can be inserted into the database - */ + #[TestDox('An object can be inserted into the database')] public function testInsertObject() { $this->loadExampleData(); @@ -317,9 +291,7 @@ public function testInsertObject() $this->assertNotNull($data->id, 'When given a key, the insertObject method should set the row ID'); } - /** - * @testdox The database server can be checked if it is running a version matching the minimum supported version - */ + #[TestDox('The database server can be checked if it is running a version matching the minimum supported version')] public function testIsMinimumVersion() { $this->assertTrue( @@ -327,9 +299,7 @@ public function testIsMinimumVersion() ); } - /** - * @testdox The first row of a result set can be loaded as an associative array, using old getQuery(true) syntax - */ + #[TestDox('The first row of a result set can be loaded as an associative array, using old getQuery(true) syntax')] public function testLoadAssocWithOldGetQueryTrueSyntax() { $this->loadExampleData(); @@ -348,9 +318,7 @@ public function testLoadAssocWithOldGetQueryTrueSyntax() ); } - /** - * @testdox The first row of a result set can be loaded as an associative array - */ + #[TestDox('The first row of a result set can be loaded as an associative array')] public function testLoadAssoc() { $this->loadExampleData(); @@ -369,9 +337,7 @@ public function testLoadAssoc() ); } - /** - * @testdox All rows of a result set can be loaded as an associative array - */ + #[TestDox('All rows of a result set can be loaded as an associative array')] public function testLoadAssocList() { $this->loadExampleData(); @@ -393,9 +359,7 @@ public function testLoadAssocList() ); } - /** - * @testdox The specified column from all rows of a result set can be loaded as an array - */ + #[TestDox('The specified column from all rows of a result set can be loaded as an array')] public function testLoadColumn() { $this->loadExampleData(); @@ -417,9 +381,7 @@ public function testLoadColumn() ); } - /** - * @testdox The first row of a result set can be loaded as a PHP object - */ + #[TestDox('The first row of a result set can be loaded as a PHP object')] public function testLoadObject() { $this->loadExampleData(); @@ -441,9 +403,7 @@ public function testLoadObject() $this->assertEquals($expected, $result); } - /** - * @testdox All rows of a result set can be loaded as PHP objects - */ + #[TestDox('All rows of a result set can be loaded as PHP objects')] public function testLoadObjectList() { $this->loadExampleData(); @@ -488,9 +448,7 @@ public function testLoadObjectList() $this->assertEquals($expected, $result); } - /** - * @testdox The first field from the first row of a result set can be loaded - */ + #[TestDox('The first field from the first row of a result set can be loaded')] public function testLoadResult() { $this->loadExampleData(); @@ -504,9 +462,7 @@ public function testLoadResult() $this->assertEquals('1', $result); } - /** - * @testdox The first row of a result set can be loaded as an array - */ + #[TestDox('The first row of a result set can be loaded as an array')] public function testLoadRow() { $this->loadExampleData(); @@ -528,9 +484,7 @@ public function testLoadRow() $this->assertEquals($expected, $result); } - /** - * @testdox All rows of a result set can be loaded as an array - */ + #[TestDox('All rows of a result set can be loaded as an array')] public function testLoadRowList() { $this->loadExampleData(); @@ -575,9 +529,7 @@ public function testLoadRowList() $this->assertEquals($expected, $result); } - /** - * @testdox A database table can be locked and unlocked - */ + #[TestDox('A database table can be locked and unlocked')] public function testLockAndUnlockTable() { $this->assertSame( @@ -601,12 +553,11 @@ public function testLockAndUnlockTable() abstract public static function dataQuoteBinary(): array; /** - * @testdox A binary value is quoted properly - * * @param string $data The binary quoted input string. * @param string $expected The expected result. */ #[DataProvider('dataQuoteBinary')] + #[TestDox('A binary value is quoted properly')] public function testQuoteBinary($data, $expected) { $this->assertSame($expected, static::$connection->quoteBinary($data)); @@ -620,13 +571,12 @@ public function testQuoteBinary($data, $expected) abstract public static function dataQuoteName(): array; /** - * @testdox A value is name quoted properly - * * @param array|string $name The identifier name to wrap in quotes, or an array of identifier names to wrap in quotes. * @param array|string $as The AS query part associated to $name. * @param array|string $expected The expected result. */ #[DataProvider('dataQuoteName')] + #[TestDox('A value is name quoted properly')] public function testQuoteName($name, $as, $expected) { $this->assertSame( @@ -635,9 +585,7 @@ public function testQuoteName($name, $as, $expected) ); } - /** - * @testdox A database table can be renamed - */ + #[TestDox('A database table can be renamed')] public function testRenameTable() { $oldTableName = '#__dbtest'; @@ -661,9 +609,7 @@ public function testRenameTable() ); } - /** - * @testdox A query monitor can be set and retrieved - */ + #[TestDox('A query monitor can be set and retrieved')] public function testGetAndSetQueryMonitor() { $this->assertNull(static::$connection->getMonitor(), 'A database driver has no monitor by default'); @@ -682,9 +628,7 @@ public function testGetAndSetQueryMonitor() ); } - /** - * @testdox A QueryInterface object can be set to the driver without an offset or limit - */ + #[TestDox('A QueryInterface object can be set to the driver without an offset or limit')] public function testSetQueryWithQueryObjectWithoutOffsetOrLimit() { $query = static::$connection->createQuery() @@ -704,9 +648,7 @@ public function testSetQueryWithQueryObjectWithoutOffsetOrLimit() ); } - /** - * @testdox A QueryInterface object can be set to the driver with an offset or limit - */ + #[TestDox('A QueryInterface object can be set to the driver with an offset or limit')] public function testSetQueryWithQueryObjectWithOffsetAndLimit() { $query = static::$connection->createQuery() @@ -740,9 +682,7 @@ public function testSetQueryWithQueryObjectWithOffsetAndLimit() ); } - /** - * @testdox A QueryInterface object can be set to the driver while retraining the offset and limit from the query - */ + #[TestDox('A QueryInterface object can be set to the driver while retraining the offset and limit from the query')] public function testSetQueryWithQueryObjectWithOffsetAndLimitOnQuery() { $query = static::$connection->createQuery() @@ -777,9 +717,7 @@ public function testSetQueryWithQueryObjectWithOffsetAndLimitOnQuery() ); } - /** - * @testdox A string can be set to the driver without an offset or limit - */ + #[TestDox('A string can be set to the driver without an offset or limit')] public function testSetQueryWithStringWithoutOffsetOrLimit() { $query = 'SELECT * FROM #__dbtest'; @@ -797,9 +735,7 @@ public function testSetQueryWithStringWithoutOffsetOrLimit() ); } - /** - * @testdox An invalid query type cannot be set to the driver - */ + #[TestDox('An invalid query type cannot be set to the driver')] public function testSetQueryWithInvalidQueryType() { $this->expectException(\InvalidArgumentException::class); @@ -807,9 +743,7 @@ public function testSetQueryWithInvalidQueryType() static::$connection->setQuery(new \stdClass()); } - /** - * @testdox A database can be selected for use - */ + #[TestDox('A database can be selected for use')] public function testSelect() { $this->assertTrue( @@ -817,9 +751,7 @@ public function testSelect() ); } - /** - * @testdox An object can be used to update a row in the database - */ + #[TestDox('An object can be used to update a row in the database')] public function testUpdateObject() { $this->loadExampleData(); @@ -850,9 +782,7 @@ public function testUpdateObject() $this->assertSame($row->title, $data->title); } - /** - * @testdox Queries using the querySet type are correctly built and executed - */ + #[TestDox('Queries using the querySet type are correctly built and executed')] public function testQuerySetWithUnionAll() { $this->loadExampleData(); @@ -888,9 +818,7 @@ public function testQuerySetWithUnionAll() ); } - /** - * @testdox Queries converted to the querySet type are correctly built and executed - */ + #[TestDox('Queries converted to the querySet type are correctly built and executed')] public function testSelectToQuerySetWithUnionAll() { $this->loadExampleData(); @@ -923,9 +851,7 @@ public function testSelectToQuerySetWithUnionAll() ); } - /** - * @testdox Select statements can be prepared once and executed repeatedly - */ + #[TestDox('Select statements can be prepared once and executed repeatedly')] public function testRepeatedSelectStatement() { $this->loadExampleData(); @@ -959,9 +885,7 @@ public function testRepeatedSelectStatement() ); } - /** - * @testdox DebugMonitor reports correct parameters with reusable query - */ + #[TestDox('DebugMonitor reports correct parameters with reusable query')] public function testMonitorWithReusableQuery() { static::$connection->setMonitor(new DebugMonitor()); @@ -1001,9 +925,7 @@ public function testMonitorWithReusableQuery() ); } - /** - * @testdox DebugMonitor reports correct parameters with repeated statement - */ + #[TestDox('DebugMonitor reports correct parameters with repeated statement')] public function testMonitorWithRepeatedStatement() { static::$connection->setMonitor(new DebugMonitor()); diff --git a/Tests/DatabaseAwareTraitTest.php b/Tests/DatabaseAwareTraitTest.php index d69e8978..676015f6 100644 --- a/Tests/DatabaseAwareTraitTest.php +++ b/Tests/DatabaseAwareTraitTest.php @@ -10,11 +10,14 @@ use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\DatabaseInterface; use Joomla\Database\Exception\DatabaseNotFoundException; +use PHPUnit\Framework\Attributes\CoversTrait; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; /** * Tests for DatabaseAwareTrait class. */ +#[CoversTrait(DatabaseAwareTrait::class)] class DatabaseAwareTraitTest extends TestCase { /** @@ -22,15 +25,10 @@ class DatabaseAwareTraitTest extends TestCase */ protected $object; - /** - * @testdox Database can be set with setDatabase() - * - * @covers \Joomla\Database\DatabaseAwareTrait - * @uses \Joomla\Database\Database - */ + #[TestDox('Database can be set with setDatabase()')] public function testGetSetDatabase(): void { - $db = $this->createMock(DatabaseInterface::class); + $db = $this->createStub(DatabaseInterface::class); $trait = new class () { use DatabaseAwareTrait; @@ -46,11 +44,7 @@ public function getDb() $this->assertSame($db, $trait->getDb()); } - /** - * @testdox getDatabase() throws an DatabaseNotFoundException, if no database is set - * - * @covers \Joomla\Database\DatabaseAwareTrait - */ + #[TestDox('getDatabase() throws an DatabaseNotFoundException, if no database is set')] public function testGetDatabaseException(): void { $this->expectException(DatabaseNotFoundException::class); diff --git a/Tests/DatabaseExporterTest.php b/Tests/DatabaseExporterTest.php index e2bb22a9..aa2757fb 100644 --- a/Tests/DatabaseExporterTest.php +++ b/Tests/DatabaseExporterTest.php @@ -7,14 +7,11 @@ namespace Joomla\Database\Tests; -use Joomla\Database\DatabaseExporter; -use Joomla\Database\DatabaseImporter; use Joomla\Database\DatabaseInterface; use Joomla\Database\Tests\Stubs\TestDatabaseExporter; -use Joomla\Database\Tests\Stubs\TestDatabaseImporter; use Joomla\Test\TestHelper; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; /** @@ -43,9 +40,7 @@ protected function setUp(): void $this->exporter = new TestDatabaseExporter(); } - /** - * @testdox The exporter is correctly configured when instantiated - */ + #[TestDox('The exporter is correctly configured when instantiated')] public function testInstantiation() { $expected = (object) [ @@ -57,9 +52,7 @@ public function testInstantiation() $this->assertSame('xml', TestHelper::getValue($this->exporter, 'asFormat')); } - /** - * @testdox The exporter can be set to XML format - */ + #[TestDox('The exporter can be set to XML format')] public function testAsXml() { $this->assertSame($this->exporter, $this->exporter->asXml(), 'The exporter supports method chaining'); @@ -93,12 +86,11 @@ public static function dataFrom(): array } /** - * @testdox The tables to be exported can be configured - * * @param string[]|string $from The name of a single table, or an array of the table names to export. * @param boolean $shouldRaiseException Flag indicating the exporter should raise an exception for an unsupported data type */ #[DataProvider('dataFrom')] + #[TestDox('The tables to be exported can be configured')] public function testFrom($from, bool $shouldRaiseException) { if ($shouldRaiseException) { @@ -110,20 +102,15 @@ public function testFrom($from, bool $shouldRaiseException) $this->assertSame((array) $from, TestHelper::getValue($this->exporter, 'from')); } - /** - * @testdox A database drier can be set to the exporter - */ + #[TestDox('A database driver can be set to the exporter')] public function testSetDbo() { - /** @var DatabaseInterface|MockObject $db */ - $db = $this->createMock(DatabaseInterface::class); + $db = $this->createStub(DatabaseInterface::class); $this->assertSame($this->exporter, $this->exporter->setDbo($db), 'The exporter supports method chaining'); } - /** - * @testdox The exporter can be configured to export with structure - */ + #[TestDox('The exporter can be configured to export with structure')] public function testWithStructure() { $this->assertSame($this->exporter, $this->exporter->withStructure(false), 'The exporter supports method chaining'); @@ -133,9 +120,7 @@ public function testWithStructure() $this->assertFalse($options->withStructure); } - /** - * @testdox The exporter can be configured to export with data - */ + #[TestDox('The exporter can be configured to export with data')] public function testWithData() { $this->assertSame($this->exporter, $this->exporter->withData(true), 'The exporter supports method chaining'); diff --git a/Tests/DatabaseFactoryTest.php b/Tests/DatabaseFactoryTest.php index 4fbfd714..7a909593 100644 --- a/Tests/DatabaseFactoryTest.php +++ b/Tests/DatabaseFactoryTest.php @@ -19,6 +19,7 @@ use Joomla\Database\StatementInterface; use Joomla\Test\TestHelper; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; /** @@ -68,12 +69,11 @@ public static function dataGetDriver(): array } /** - * @testdox The factory builds a database driver correctly - * * @param string $adapter The type of adapter to create * @param boolean $shouldRaiseException Flag indicating the factory should raise an exception for an unsupported adapter */ #[DataProvider('dataGetDriver')] + #[TestDox('The factory builds a database driver correctly')] public function testGetDriver(string $adapter, bool $shouldRaiseException) { if ($shouldRaiseException) { @@ -115,13 +115,12 @@ public static function dataGetExporter(): array } /** - * @testdox The factory builds a database exporter correctly - * * @param string $adapter The type of adapter to create * @param boolean $shouldRaiseException Flag indicating the factory should raise an exception for an unsupported adapter * @param DatabaseDriver|null $databaseDriver The optional database driver to be injected into the exporter */ #[DataProvider('dataGetExporter')] + #[TestDox('The factory builds a database exporter correctly')] public function testGetExporter(string $adapter, bool $shouldRaiseException, bool $createDb) { if ($shouldRaiseException) { @@ -131,7 +130,7 @@ public function testGetExporter(string $adapter, bool $shouldRaiseException, boo $databaseDriver = null; if ($createDb) { - $databaseDriver = $this->createMock(MysqliDriver::class); + $databaseDriver = $this->createStub(MysqliDriver::class); } $exporter = $this->factory->getExporter($adapter, $databaseDriver); @@ -178,13 +177,12 @@ public static function dataGetImporter(): array } /** - * @testdox The factory builds a database importer correctly - * * @param string $adapter The type of adapter to create * @param boolean $shouldRaiseException Flag indicating the factory should raise an exception for an unsupported adapter * @param boolean $createDb The optional database driver to be injected into the importer */ #[DataProvider('dataGetImporter')] + #[TestDox('The factory builds a database importer correctly')] public function testGetImporter(string $adapter, bool $shouldRaiseException, bool $createDb) { if ($shouldRaiseException) { @@ -194,7 +192,7 @@ public function testGetImporter(string $adapter, bool $shouldRaiseException, boo $databaseDriver = null; if ($createDb) { - $databaseDriver = $this->createMock(MysqliDriver::class); + $databaseDriver = $this->createStub(MysqliDriver::class); } $importer = $this->factory->getImporter($adapter, $databaseDriver); @@ -228,18 +226,17 @@ public static function dataGetIterator(): array } /** - * @testdox The factory builds a database iterator correctly - * * @param string $adapter The type of adapter to create * @param bool $createStatement Statement holding the result set to be iterated. */ #[DataProvider('dataGetIterator')] + #[TestDox('The factory builds a database iterator correctly')] public function testGetIterator(string $adapter, bool $createStatement) { $statement = null; if ($createStatement) { - $statement = $this->createMock(StatementInterface::class); + $statement = $this->createStub(StatementInterface::class); } $this->assertInstanceOf( @@ -271,13 +268,12 @@ public static function dataGetQuery(): array } /** - * @testdox The factory builds a database query object correctly - * * @param string $adapter The type of adapter to create * @param boolean $shouldRaiseException Flag indicating the factory should raise an exception for an unsupported adapter * @param boolean $createDb The optional database driver to be injected into the importer */ #[DataProvider('dataGetQuery')] + #[TestDox('The factory builds a database query object correctly')] public function testGetQuery(string $adapter, bool $shouldRaiseException, bool $createDb) { if ($shouldRaiseException) { @@ -287,7 +283,7 @@ public function testGetQuery(string $adapter, bool $shouldRaiseException, bool $ $databaseDriver = null; if ($createDb) { - $databaseDriver = $this->createMock(MysqliDriver::class); + $databaseDriver = $this->createStub(MysqliDriver::class); } $this->assertInstanceOf( diff --git a/Tests/DatabaseImporterTest.php b/Tests/DatabaseImporterTest.php index c3e36916..f3724e0c 100644 --- a/Tests/DatabaseImporterTest.php +++ b/Tests/DatabaseImporterTest.php @@ -7,12 +7,10 @@ namespace Joomla\Database\Tests; -use Joomla\Database\DatabaseImporter; use Joomla\Database\DatabaseInterface; use Joomla\Database\Tests\Stubs\TestDatabaseImporter; -use Joomla\Database\Tests\Stubs\TestDatabaseQuery; use Joomla\Test\TestHelper; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; /** @@ -41,9 +39,7 @@ protected function setUp(): void $this->importer = new TestDatabaseImporter(); } - /** - * @testdox The importer is correctly configured when instantiated - */ + #[TestDox('The importer is correctly configured when instantiated')] public function testInstantiation() { $expected = (object) [ @@ -54,9 +50,7 @@ public function testInstantiation() $this->assertSame('xml', TestHelper::getValue($this->importer, 'asFormat')); } - /** - * @testdox The importer can be set to XML format - */ + #[TestDox('The importer can be set to XML format')] public function testAsXml() { $this->assertSame($this->importer, $this->importer->asXml(), 'The importer supports method chaining'); @@ -64,20 +58,15 @@ public function testAsXml() $this->assertSame('xml', TestHelper::getValue($this->importer, 'asFormat')); } - /** - * @testdox A database drier can be set to the importer - */ + #[TestDox('A database driver can be set to the importer')] public function testSetDbo() { - /** @var DatabaseInterface|MockObject $db */ - $db = $this->createMock(DatabaseInterface::class); + $db = $this->createStub(DatabaseInterface::class); $this->assertSame($this->importer, $this->importer->setDbo($db), 'The importer supports method chaining'); } - /** - * @testdox The importer can be configured to export with structure - */ + #[TestDox('The importer can be configured to export with structure')] public function testWithStructure() { $this->assertSame($this->importer, $this->importer->withStructure(false), 'The importer supports method chaining'); diff --git a/Tests/DatabaseIteratorTest.php b/Tests/DatabaseIteratorTest.php index 80697e55..e3fad8ff 100644 --- a/Tests/DatabaseIteratorTest.php +++ b/Tests/DatabaseIteratorTest.php @@ -9,7 +9,9 @@ use Joomla\Database\DatabaseIterator; use Joomla\Database\FetchMode; use Joomla\Database\StatementInterface; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -17,9 +19,7 @@ */ class DatabaseIteratorTest extends TestCase { - /** - * @testdox The iterator is instantiated and the first object from the result set is set as the current key - */ + #[TestDox('The iterator is instantiated and the first object from the result set is set as the current key')] public function testInstantiation() { /** @var StatementInterface|MockObject $statement */ @@ -27,7 +27,7 @@ public function testInstantiation() $i = 0; - $statement->expects($this->any()) + $statement->expects($this->once()) ->method('fetch') ->willReturnCallback( function () use ($i) { @@ -51,9 +51,7 @@ function () use ($i) { $this->assertEquals($expected, $iterator->current()); } - /** - * @testdox The iterator can iterate over all rows in a result set - */ + #[TestDox('The iterator can iterate over all rows in a result set')] public function testIteration() { /** @var StatementInterface|MockObject $statement */ @@ -105,9 +103,7 @@ public function testIteration() $this->assertEquals($expected, iterator_to_array($iterator)); } - /** - * @testdox The iterator can iterate over all rows in a result set with a custom key - */ + #[TestDox('The iterator can iterate over all rows in a result set with a custom key')] public function testIterationWithCustomKey() { /** @var StatementInterface|MockObject $statement */ @@ -164,9 +160,7 @@ public function testIterationWithCustomKey() $this->assertEquals($expected, iterator_to_array($iterator)); } - /** - * @testdox The iterator can iterate over all rows in a result set with a custom PHP class - */ + #[TestDox('The iterator can iterate over all rows in a result set with a custom PHP class')] public function testIterationWithCustomClass() { /** @var StatementInterface|MockObject $statement */ @@ -204,9 +198,7 @@ public function testIterationWithCustomClass() $this->assertEquals($expected, iterator_to_array($iterator)); } - /** - * @testdox The iterator can be counted - */ + #[TestDox('The iterator can be counted')] public function testCount() { /** @var StatementInterface|MockObject $statement */ @@ -222,15 +214,13 @@ public function testCount() $this->assertCount(42, $iterator); } - /** - * @testdox The iterator cannot be created if the class that objects should be placed in does not exist - */ + #[TestDox('The iterator cannot be created if the class that objects should be placed in does not exist')] public function testConstructorExceptionForNonExistingClass() { $this->expectException(\InvalidArgumentException::class); - /** @var StatementInterface|MockObject $statement */ - $statement = $this->createMock(StatementInterface::class); + /** @var StatementInterface|Stub $statement */ + $statement = $this->createStub(StatementInterface::class); $iterator = new DatabaseIterator($statement, null, \NonExistingClass::class); } diff --git a/Tests/DatabaseQueryTest.php b/Tests/DatabaseQueryTest.php index e29402af..96333637 100644 --- a/Tests/DatabaseQueryTest.php +++ b/Tests/DatabaseQueryTest.php @@ -13,7 +13,8 @@ use Joomla\Database\ParameterType; use Joomla\Database\Tests\Stubs\TestDatabaseQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -24,14 +25,14 @@ class DatabaseQueryTest extends TestCase /** * Object being tested * - * @var MockObject|DatabaseQuery + * @var DatabaseQuery */ private $query; /** * Mock database driver * - * @var MockObject|DatabaseInterface + * @var Stub|DatabaseInterface */ private $db; @@ -46,13 +47,11 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(DatabaseInterface::class); + $this->db = $this->createStub(DatabaseInterface::class); $this->query = new TestDatabaseQuery($this->db); } - /** - * @testdox The call method correctly creates and manages a CALL query element - */ + #[TestDox('The call method correctly creates and manages a CALL query element')] public function testCall() { $this->assertSame($this->query, $this->query->call('foo'), 'The query builder supports method chaining'); @@ -64,9 +63,7 @@ public function testCall() ); } - /** - * @testdox The call method raises an exception if changing the query type - */ + #[TestDox('The call method raises an exception if changing the query type')] public function testCallChangeQueryType() { $this->expectException(QueryTypeAlreadyDefinedException::class); @@ -76,25 +73,19 @@ public function testCallChangeQueryType() ->call('foo'); } - /** - * @testdox A string is cast as a character string for the driver - */ + #[TestDox('A string is cast as a character string for the driver')] public function testCastAs() { $this->assertSame('123', $this->query->castAs('CHAR', '123')); } - /** - * @testdox The length param is ignored for castAs when the sql driver doesn't support it - */ + #[TestDox("The length param is ignored for castAs when the sql driver doesn't support it")] public function testCastAsLengthParamIgnoredWhenNotSupported() { $this->assertSame('123', $this->query->castAs('CHAR', '123', 2)); } - /** - * @testdox Test an unknown type case return an unknown type exception - */ + #[TestDox('Test an unknown type case return an unknown type exception')] public function testCastAsWithUnknownType() { $this->expectException(UnknownTypeException::class); @@ -115,14 +106,13 @@ public static function dataCharLength(): array } /** - * @testdox A SQL statement for checking the character length of a field is generated - * * @param string $field A value. * @param string|null $operator Comparison operator between charLength integer value and $condition * @param string|null $condition Integer value to compare charLength with. * @param string $expected The expected query string. */ #[DataProvider('dataCharLength')] + #[TestDox('A SQL statement for checking the character length of a field is generated')] public function testCharLength(string $field, ?string $operator, ?string $condition, string $expected) { $this->assertSame( @@ -131,9 +121,7 @@ public function testCharLength(string $field, ?string $operator, ?string $condit ); } - /** - * @testdox The columns method correctly creates and manages a list of columns - */ + #[TestDox('The columns method correctly creates and manages a list of columns')] public function testColumns() { $this->assertSame($this->query, $this->query->columns('foo'), 'The query builder supports method chaining'); @@ -159,17 +147,15 @@ public static function dataConcatenate(): array } /** - * @testdox A SQL statement for concatenating values is generated - * * @param string[] $values An array of values to concatenate. * @param string|null $separator As separator to place between each value. * @param string $expected The expected query string. */ #[DataProvider('dataConcatenate')] + #[TestDox('A SQL statement for concatenating values is generated')] public function testConcatenate(array $values, ?string $separator, string $expected) { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); @@ -180,9 +166,7 @@ public function testConcatenate(array $values, ?string $separator, string $expec ); } - /** - * @testdox A SQL statement for the current timestamp is generated - */ + #[TestDox('A SQL statement for the current timestamp is generated')] public function testCurrentTimestamp() { $this->assertSame( @@ -205,14 +189,13 @@ public static function dataDateAdd(): array } /** - * @testdox A SQL statement for adding date values is generated - * * @param string $date The db quoted string representation of the date to add to. May be date or datetime * @param string $interval The string representation of the appropriate number of units * @param string $datePart The part of the date to perform the addition on * @param string $expected The expected query string. */ #[DataProvider('dataDateAdd')] + #[TestDox('A SQL statement for adding date values is generated')] public function testDateAdd(string $date, string $interval, string $datePart, string $expected) { $this->assertSame( @@ -221,9 +204,7 @@ public function testDateAdd(string $date, string $interval, string $datePart, st ); } - /** - * @testdox The delete method correctly creates a DELETE query element without a table name - */ + #[TestDox('The delete method correctly creates a DELETE query element without a table name')] public function testDeleteWithoutTable() { $this->assertSame($this->query, $this->query->delete(), 'The query builder supports method chaining'); @@ -232,9 +213,7 @@ public function testDeleteWithoutTable() $this->assertNull($this->query->from); } - /** - * @testdox The delete method correctly creates a DELETE and FROM query element with a table name - */ + #[TestDox('The delete method correctly creates a DELETE and FROM query element with a table name')] public function testDeleteWithTable() { $this->assertSame($this->query, $this->query->delete('#__content'), 'The query builder supports method chaining'); @@ -243,9 +222,7 @@ public function testDeleteWithTable() $this->assertNotNull($this->query->from); } - /** - * @testdox The delete method raises an exception if changing the query type - */ + #[TestDox('The delete method raises an exception if changing the query type')] public function testDeleteChangeQueryType() { $this->expectException(QueryTypeAlreadyDefinedException::class); @@ -255,9 +232,7 @@ public function testDeleteChangeQueryType() ->delete('foo'); } - /** - * @testdox The exec method correctly creates and manages a EXEC query element - */ + #[TestDox('The exec method correctly creates and manages a EXEC query element')] public function testExec() { $this->assertSame($this->query, $this->query->exec('foo'), 'The query builder supports method chaining'); @@ -269,9 +244,7 @@ public function testExec() ); } - /** - * @testdox The exec method raises an exception if changing the query type - */ + #[TestDox('The exec method raises an exception if changing the query type')] public function testExecChangeQueryType() { $this->expectException(QueryTypeAlreadyDefinedException::class); @@ -281,9 +254,7 @@ public function testExecChangeQueryType() ->exec('foo'); } - /** - * @testdox A SQL statement for the MySQL find_in_set() function is generated - */ + #[TestDox('A SQL statement for the MySQL find_in_set() function is generated')] public function testFindInSet() { $this->assertSame( @@ -292,9 +263,7 @@ public function testFindInSet() ); } - /** - * @testdox The from method correctly creates and manages a FROM query element - */ + #[TestDox('The from method correctly creates and manages a FROM query element')] public function testFrom() { $this->assertSame($this->query, $this->query->from('foo'), 'The query builder supports method chaining'); @@ -306,9 +275,7 @@ public function testFrom() ); } - /** - * @testdox The query can be aliased - */ + #[TestDox('The query can be aliased')] public function testAlias() { $this->assertSame($this->query, $this->query->alias('foo'), 'The query builder supports method chaining'); @@ -319,9 +286,7 @@ public function testAlias() ); } - /** - * @testdox A SQL statement to extract the year from a date is generated - */ + #[TestDox('A SQL statement to extract the year from a date is generated')] public function testYear() { $this->assertSame( @@ -330,9 +295,7 @@ public function testYear() ); } - /** - * @testdox A SQL statement to extract the month from a date is generated - */ + #[TestDox('A SQL statement to extract the month from a date is generated')] public function testMonth() { $this->assertSame( @@ -341,9 +304,7 @@ public function testMonth() ); } - /** - * @testdox A SQL statement to extract the day from a date is generated - */ + #[TestDox('A SQL statement to extract the day from a date is generated')] public function testDay() { $this->assertSame( @@ -352,9 +313,7 @@ public function testDay() ); } - /** - * @testdox A SQL statement to extract the hour from a date is generated - */ + #[TestDox('A SQL statement to extract the hour from a date is generated')] public function testHour() { $this->assertSame( @@ -363,9 +322,7 @@ public function testHour() ); } - /** - * @testdox A SQL statement to extract the minute from a date is generated - */ + #[TestDox('A SQL statement to extract the minute from a date is generated')] public function testMinute() { $this->assertSame( @@ -374,9 +331,7 @@ public function testMinute() ); } - /** - * @testdox A SQL statement to extract the second from a date is generated - */ + #[TestDox('A SQL statement to extract the second from a date is generated')] public function testSecond() { $this->assertSame( @@ -385,9 +340,7 @@ public function testSecond() ); } - /** - * @testdox The group method correctly creates and manages a GROUP BY query element - */ + #[TestDox('The group method correctly creates and manages a GROUP BY query element')] public function testGroup() { $this->assertSame($this->query, $this->query->group('foo'), 'The query builder supports method chaining'); @@ -399,9 +352,7 @@ public function testGroup() ); } - /** - * @testdox The having method correctly creates and manages a HAVING query element - */ + #[TestDox('The having method correctly creates and manages a HAVING query element')] public function testHaving() { $this->assertSame($this->query, $this->query->having('foo'), 'The query builder supports method chaining'); @@ -413,9 +364,7 @@ public function testHaving() ); } - /** - * @testdox The insert method correctly creates a INSERT query element - */ + #[TestDox('The insert method correctly creates a INSERT query element')] public function testInsert() { $this->assertSame($this->query, $this->query->insert('foo'), 'The query builder supports method chaining'); @@ -423,9 +372,7 @@ public function testInsert() $this->assertNotNull($this->query->insert); } - /** - * @testdox The insert method raises an exception if changing the query type - */ + #[TestDox('The insert method raises an exception if changing the query type')] public function testInsertChangeQueryType() { $this->expectException(QueryTypeAlreadyDefinedException::class); @@ -435,9 +382,7 @@ public function testInsertChangeQueryType() ->insert('foo'); } - /** - * @testdox The join method correctly creates a JOIN query element - */ + #[TestDox('The join method correctly creates a JOIN query element')] public function testJoin() { $this->assertSame($this->query, $this->query->join('inner', 'foo'), 'The query builder supports method chaining'); @@ -449,9 +394,7 @@ public function testJoin() ); } - /** - * @testdox The innerJoin method correctly creates a INNER JOIN query element - */ + #[TestDox('The innerJoin method correctly creates a INNER JOIN query element')] public function testInnerJoin() { $this->assertSame($this->query, $this->query->innerJoin('foo'), 'The query builder supports method chaining'); @@ -463,9 +406,7 @@ public function testInnerJoin() ); } - /** - * @testdox The outerJoin method correctly creates a OUTER JOIN query element - */ + #[TestDox('The outerJoin method correctly creates a OUTER JOIN query element')] public function testOuterJoin() { $this->assertSame($this->query, $this->query->outerJoin('foo'), 'The query builder supports method chaining'); @@ -477,9 +418,7 @@ public function testOuterJoin() ); } - /** - * @testdox The leftJoin method correctly creates a LEFT JOIN query element - */ + #[TestDox('The leftJoin method correctly creates a LEFT JOIN query element')] public function testLeftJoin() { $this->assertSame($this->query, $this->query->leftJoin('foo'), 'The query builder supports method chaining'); @@ -491,9 +430,7 @@ public function testLeftJoin() ); } - /** - * @testdox The rightJoin method correctly creates a RIGHT JOIN query element - */ + #[TestDox('The rightJoin method correctly creates a RIGHT JOIN query element')] public function testRightJoin() { $this->assertSame($this->query, $this->query->rightJoin('foo'), 'The query builder supports method chaining'); @@ -505,9 +442,7 @@ public function testRightJoin() ); } - /** - * @testdox A SQL statement to get the length of a field is generated - */ + #[TestDox('A SQL statement to get the length of a field is generated')] public function testLength() { $this->assertSame( @@ -530,19 +465,21 @@ public static function dataNullDate(): array } /** - * @testdox The null date from the database driver is retrieved - * * @param boolean $quoted Optionally wraps the null date in database quotes (true by default). * @param string $expected The expected query string. */ #[DataProvider('dataNullDate')] + #[TestDox('The null date from the database driver is retrieved')] public function testNullDate(bool $quoted, string $expected) { - $this->db->expects($this->once()) + $db = $this->createMock(DatabaseInterface::class); + $query = new TestDatabaseQuery($db); + + $db->expects($this->once()) ->method('getNullDate') ->willReturn('0000-00-00 00:00:00'); - $this->db->expects($this->any()) + $db->expects($this->exactly((int) $quoted)) ->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; @@ -550,13 +487,11 @@ public function testNullDate(bool $quoted, string $expected) $this->assertSame( $expected, - $this->query->nullDate($quoted) + $query->nullDate($quoted) ); } - /** - * @testdox The null date cannot be retrieved from the database driver if no driver is present - */ + #[TestDox('The null date cannot be retrieved from the database driver if no driver is present')] public function testNullDateException() { $this->expectException(\RuntimeException::class); @@ -566,9 +501,7 @@ public function testNullDateException() $query->nullDate(); } - /** - * @testdox A SQL statement to determine if a field contains a null date is generated when the query has no known null dates - */ + #[TestDox('A SQL statement to determine if a field contains a null date is generated when the query has no known null dates')] public function testIsNullDatetimeNoDates() { $this->assertSame( @@ -577,12 +510,12 @@ public function testIsNullDatetimeNoDates() ); } - /** - * @testdox A SQL statement to determine if a field contains a null date is generated when the query has known null dates - */ + #[TestDox('A SQL statement to determine if a field contains a null date is generated when the query has known null dates')] public function testIsNullDatetimeWithDates() { - $this->db->expects($this->any()) + $db = $this->createMock(DatabaseInterface::class); + + $db->expects($this->once()) ->method('quote') ->willReturnCallback(function ($text, $escape = true) { foreach ($text as $k => $v) { @@ -592,7 +525,7 @@ public function testIsNullDatetimeWithDates() return $text; }); - $query = new class ($this->db) extends DatabaseQuery { + $query = new class ($db) extends DatabaseQuery { protected $nullDatetimeList = ['0000-00-00 00:00:00', '1000-01-01 00:00:00']; public function groupConcat($expression, $separator = ',') @@ -612,9 +545,7 @@ public function processLimit($query, $limit, $offset = 0) ); } - /** - * @testdox A SQL statement to determine if a field contains a null date cannot be retrieved from the database driver if no driver is present - */ + #[TestDox('A SQL statement to determine if a field contains a null date cannot be retrieved from the database driver if no driver is present')] public function testIsNullDatetimeException() { $this->expectException(\RuntimeException::class); @@ -624,9 +555,7 @@ public function testIsNullDatetimeException() $query->isNullDatetime('a.created'); } - /** - * @testdox The order method correctly creates and manages a ORDER BY query element - */ + #[TestDox('The order method correctly creates and manages a ORDER BY query element')] public function testOrder() { $this->assertSame($this->query, $this->query->order('foo'), 'The query builder supports method chaining'); @@ -638,12 +567,13 @@ public function testOrder() ); } - /** - * @testdox A string can be quoted - */ + #[TestDox('A string can be quoted')] public function testQuote() { - $this->db->expects($this->any()) + $db = $this->createMock(DatabaseInterface::class); + $query = new TestDatabaseQuery($db); + + $db->expects($this->once()) ->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; @@ -651,13 +581,11 @@ public function testQuote() $this->assertSame( "'foo'", - $this->query->quote('foo') + $query->quote('foo') ); } - /** - * @testdox A string cannot be quoted if no database driver is present - */ + #[TestDox('A string cannot be quoted if no database driver is present')] public function testQuoteException() { $this->expectException(\RuntimeException::class); @@ -667,12 +595,13 @@ public function testQuoteException() $query->quote('foo'); } - /** - * @testdox A string can be quoted as a field identifier - */ + #[TestDox('A string can be quoted as a field identifier')] public function testQuoteName() { - $this->db->expects($this->any()) + $db = $this->createMock(DatabaseInterface::class); + $query = new TestDatabaseQuery($db); + + $db->expects($this->once()) ->method('quoteName') ->willReturnCallback(function ($text, $escape = true) { return "`" . $text . "`"; @@ -680,13 +609,11 @@ public function testQuoteName() $this->assertSame( "`foo`", - $this->query->quoteName('foo') + $query->quoteName('foo') ); } - /** - * @testdox A string cannot be quoted as a field identifier if no database driver is present - */ + #[TestDox('A string cannot be quoted as a field identifier if no database driver is present')] public function testQuoteNameException() { $this->expectException(\RuntimeException::class); @@ -696,9 +623,7 @@ public function testQuoteNameException() $query->quoteName('foo'); } - /** - * @testdox A SQL statement to get a random floating point value is generated - */ + #[TestDox('A SQL statement to get a random floating point value is generated')] public function testRand() { $this->assertSame( @@ -707,9 +632,7 @@ public function testRand() ); } - /** - * @testdox A SQL statement to prepend a string with a regex operator is generated - */ + #[TestDox('A SQL statement to prepend a string with a regex operator is generated')] public function testRegexp() { $this->assertSame( @@ -718,9 +641,7 @@ public function testRegexp() ); } - /** - * @testdox The select method correctly creates and manages a SELECT query element - */ + #[TestDox('The select method correctly creates and manages a SELECT query element')] public function testSelect() { $this->assertSame($this->query, $this->query->select('foo'), 'The query builder supports method chaining'); @@ -732,9 +653,7 @@ public function testSelect() ); } - /** - * @testdox The select method raises an exception if changing the query type - */ + #[TestDox('The select method raises an exception if changing the query type')] public function testSelectChangeQueryType() { $this->expectException(QueryTypeAlreadyDefinedException::class); @@ -743,9 +662,7 @@ public function testSelectChangeQueryType() ->select('foo'); } - /** - * @testdox The set method correctly creates and manages a SET query element - */ + #[TestDox('The set method correctly creates and manages a SET query element')] public function testSet() { $this->assertSame($this->query, $this->query->set('foo'), 'The query builder supports method chaining'); @@ -757,9 +674,7 @@ public function testSet() ); } - /** - * @testdox The setLimit method correctly manages the limit and offset for a query - */ + #[TestDox('The setLimit method correctly manages the limit and offset for a query')] public function testSetLimit() { $this->assertSame($this->query, $this->query->setLimit(10, 25), 'The query builder supports method chaining'); @@ -775,9 +690,7 @@ public function testSetLimit() ); } - /** - * @testdox The setQuery method correctly manages an injected SQL query - */ + #[TestDox('The setQuery method correctly manages an injected SQL query')] public function testSetQuery() { $query = 'SELECT foo FROM bar'; @@ -790,9 +703,7 @@ public function testSetQuery() ); } - /** - * @testdox The update method correctly creates a UPDATE query element - */ + #[TestDox('The update method correctly creates a UPDATE query element')] public function testUpdate() { $this->assertSame($this->query, $this->query->update('foo'), 'The query builder supports method chaining'); @@ -800,9 +711,7 @@ public function testUpdate() $this->assertNotNull($this->query->update); } - /** - * @testdox The update method raises an exception if changing the query type - */ + #[TestDox('The update method raises an exception if changing the query type')] public function testUpdateChangeQueryType() { $this->expectException(QueryTypeAlreadyDefinedException::class); @@ -812,9 +721,7 @@ public function testUpdateChangeQueryType() ->update('foo'); } - /** - * @testdox The values method correctly creates and manages a list of values - */ + #[TestDox('The values method correctly creates and manages a list of values')] public function testValues() { $this->assertSame($this->query, $this->query->values('foo'), 'The query builder supports method chaining'); @@ -826,9 +733,7 @@ public function testValues() ); } - /** - * @testdox The where method correctly creates and manages a WHERE query element - */ + #[TestDox('The where method correctly creates and manages a WHERE query element')] public function testWhere() { $this->assertSame($this->query, $this->query->where('foo'), 'The query builder supports method chaining'); @@ -840,9 +745,7 @@ public function testWhere() ); } - /** - * @testdox The whereIn method correctly creates and manages a WHERE query element with parameter binding - */ + #[TestDox('The whereIn method correctly creates and manages a WHERE query element with parameter binding')] public function testWhereIn() { $this->assertSame($this->query, $this->query->whereIn('foo', [1, 2]), 'The query builder supports method chaining'); @@ -854,9 +757,7 @@ public function testWhereIn() ); } - /** - * @testdox The whereNotIn method correctly creates and manages a WHERE query element with parameter binding - */ + #[TestDox('The whereNotIn method correctly creates and manages a WHERE query element with parameter binding')] public function testWhereNotIn() { $this->assertSame($this->query, $this->query->whereNotIn('foo', [1, 2]), 'The query builder supports method chaining'); @@ -868,9 +769,7 @@ public function testWhereNotIn() ); } - /** - * @testdox The extendWhere method correctly overrides a WHERE query element - */ + #[TestDox('The extendWhere method correctly overrides a WHERE query element')] public function testExtendWhere() { $this->query->where('foo'); @@ -882,9 +781,7 @@ public function testExtendWhere() ); } - /** - * @testdox The orWhere method correctly overrides a WHERE query element - */ + #[TestDox('The orWhere method correctly overrides a WHERE query element')] public function testOrWhere() { $this->query->where('foo'); @@ -896,9 +793,7 @@ public function testOrWhere() ); } - /** - * @testdox The andWhere method correctly overrides a WHERE query element - */ + #[TestDox('The andWhere method correctly overrides a WHERE query element')] public function testAndWhere() { $this->query->where('foo'); @@ -940,8 +835,6 @@ public static function dataBind(): array } /** - * @testdox The bind method records a bound parameter for the query - * * @param array|string|integer $key The key that will be used in your SQL query to reference the value. Usually of * the form ':key', but can also be an integer. * @param mixed $value The value that will be bound. It can be an array, in this case it has to be @@ -952,6 +845,7 @@ public static function dataBind(): array * @param array $expected The expected structure of `$bounded` */ #[DataProvider('dataBind')] + #[TestDox('The bind method records a bound parameter for the query')] public function testBind($key, $value, $dataType, $expected) { $this->assertSame($this->query, $this->query->bind($key, $value, $dataType), 'The query builder supports method chaining'); @@ -962,9 +856,7 @@ public function testBind($key, $value, $dataType, $expected) ); } - /** - * @testdox The bind method does not record bound parameters when the keys and values are an unbalanced number of items - */ + #[TestDox('The bind method does not record bound parameters when the keys and values are an unbalanced number of items')] public function testBindUnbalancedKeyValue() { $this->expectException(\InvalidArgumentException::class); @@ -977,9 +869,7 @@ public function testBindUnbalancedKeyValue() $this->query->bind($keys, $values, $dataTypes); } - /** - * @testdox The bind method does not record bound parameters when the keys and data types are an unbalanced number of items - */ + #[TestDox('The bind method does not record bound parameters when the keys and data types are an unbalanced number of items')] public function testBindUnbalancedKeyDataType() { $this->expectException(\InvalidArgumentException::class); @@ -992,9 +882,7 @@ public function testBindUnbalancedKeyDataType() $this->query->bind($keys, $values, $dataTypes); } - /** - * @testdox Values are stored by reference - */ + #[TestDox('Values are stored by reference')] public function testBindByReference() { $key = 1; @@ -1010,9 +898,7 @@ public function testBindByReference() ); } - /** - * @testdox bind() does not rely on index sequence - */ + #[TestDox('bind() does not rely on index sequence')] public function testBindIndexSequence() { $keys = [1, 2]; @@ -1033,9 +919,7 @@ public function testBindIndexSequence() ); } - /** - * @testdox bind() accepts associated value arrays - */ + #[TestDox('bind() accepts associated value arrays')] public function testBindAssoc() { $keys = [1, 2]; @@ -1053,9 +937,7 @@ public function testBindAssoc() ); } - /** - * @testdox The bindArray method creates bound parameters for an array and returns the parameter names - */ + #[TestDox('The bindArray method creates bound parameters for an array and returns the parameter names')] public function testBindArray() { $this->assertSame( @@ -1064,9 +946,7 @@ public function testBindArray() ); } - /** - * @testdox The union method correctly creates and manages a merge query element - */ + #[TestDox('The union method correctly creates and manages a merge query element')] public function testUnion() { $this->assertSame($this->query, $this->query->union('foo'), 'The query builder supports method chaining'); @@ -1078,9 +958,7 @@ public function testUnion() ); } - /** - * @testdox The unionAll method correctly creates and manages a merge query element - */ + #[TestDox('The unionAll method correctly creates and manages a merge query element')] public function testUnionAll() { $this->assertSame($this->query, $this->query->unionAll('foo'), 'The query builder supports method chaining'); @@ -1092,9 +970,7 @@ public function testUnionAll() ); } - /** - * @testdox The querySet method correctly marks the query type - */ + #[TestDox('The querySet method correctly marks the query type')] public function testQuerySet() { $this->assertSame($this->query, $this->query->querySet('SELECT foo FROM bar'), 'The query builder supports method chaining'); @@ -1105,9 +981,7 @@ public function testQuerySet() ); } - /** - * @testdox The query is converted to a querySet type - */ + #[TestDox('The query is converted to a querySet type')] public function testToQuerySet() { $this->query->setQuery('SELECT foo FROM bar'); @@ -1117,9 +991,7 @@ public function testToQuerySet() $this->assertNotSame($querySetQuery, $this->query); } - /** - * @testdox A query object containing a SELECT query is converted to a proper SQL string - */ + #[TestDox('A query object containing a SELECT query is converted to a proper SQL string')] public function testCastingToStringSelect() { $query = new class ($this->db) extends DatabaseQuery { @@ -1160,9 +1032,7 @@ public function processLimit($query, $limit, $offset = 0) $this->assertSame($expected, (string) $query); } - /** - * @testdox A query object containing an aliased SELECT query is converted to a proper SQL string - */ + #[TestDox('A query object containing an aliased SELECT query is converted to a proper SQL string')] public function testCastingToStringSelectAliased() { $query = new class ($this->db) extends DatabaseQuery { @@ -1190,9 +1060,7 @@ public function processLimit($query, $limit, $offset = 0) $this->assertSame($expected, (string) $query); } - /** - * @testdox A query object containing a DELETE query is converted to a proper SQL string - */ + #[TestDox('A query object containing a DELETE query is converted to a proper SQL string')] public function testCastingToStringDelete() { $query = new class ($this->db) extends DatabaseQuery { @@ -1220,9 +1088,7 @@ public function processLimit($query, $limit, $offset = 0) $this->assertSame($expected, (string) $query); } - /** - * @testdox A query object containing a UPDATE query is converted to a proper SQL string - */ + #[TestDox('A query object containing a UPDATE query is converted to a proper SQL string')] public function testCastingToStringUpdate() { $query = new class ($this->db) extends DatabaseQuery { @@ -1250,18 +1116,18 @@ public function processLimit($query, $limit, $offset = 0) $this->assertSame($expected, (string) $query); } - /** - * @testdox A query object containing a INSERT query with SET notation is converted to a proper SQL string - */ + #[TestDox('A query object containing a INSERT query with SET notation is converted to a proper SQL string')] public function testCastingToStringInsertSet() { - $this->db->expects($this->any()) + $db = $this->createMock(DatabaseInterface::class); + + $db->expects($this->once()) ->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); - $query = new class ($this->db) extends DatabaseQuery { + $query = new class ($db) extends DatabaseQuery { public function groupConcat($expression, $separator = ',') { return ''; @@ -1284,18 +1150,18 @@ public function processLimit($query, $limit, $offset = 0) $this->assertSame($expected, (string) $query); } - /** - * @testdox A query object containing a INSERT query with COLUMNS/VALUES notation is converted to a proper SQL string - */ + #[TestDox('A query object containing a INSERT query with COLUMNS/VALUES notation is converted to a proper SQL string')] public function testCastingToStringInsertColumnsValues() { - $this->db->expects($this->any()) + $db = $this->createMock(DatabaseInterface::class); + + $db->expects($this->once()) ->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); - $query = new class ($this->db) extends DatabaseQuery { + $query = new class ($db) extends DatabaseQuery { public function groupConcat($expression, $separator = ',') { return ''; @@ -1319,9 +1185,7 @@ public function processLimit($query, $limit, $offset = 0) $this->assertSame($expected, (string) $query); } - /** - * @testdox A query object containing a CALL query is converted to a proper SQL string - */ + #[TestDox('A query object containing a CALL query is converted to a proper SQL string')] public function testCastingToStringCall() { $query = new class ($this->db) extends DatabaseQuery { @@ -1343,9 +1207,7 @@ public function processLimit($query, $limit, $offset = 0) $this->assertSame($expected, (string) $query); } - /** - * @testdox A query object containing a EXEC query is converted to a proper SQL string - */ + #[TestDox('A query object containing a EXEC query is converted to a proper SQL string')] public function testCastingToStringExec() { $query = new class ($this->db) extends DatabaseQuery { @@ -1367,9 +1229,7 @@ public function processLimit($query, $limit, $offset = 0) $this->assertSame($expected, (string) $query); } - /** - * @testdox A query object containing an injected query is converted to a proper SQL string - */ + #[TestDox('A query object containing an injected query is converted to a proper SQL string')] public function testCastingToStringInjectedQuery() { $query = new class ($this->db) extends DatabaseQuery { diff --git a/Tests/Monitor/ChainedMonitorTest.php b/Tests/Monitor/ChainedMonitorTest.php index a609c24f..cfd1922b 100644 --- a/Tests/Monitor/ChainedMonitorTest.php +++ b/Tests/Monitor/ChainedMonitorTest.php @@ -8,6 +8,7 @@ use Joomla\Database\Monitor\ChainedMonitor; use Joomla\Database\QueryMonitorInterface; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; /** @@ -36,9 +37,7 @@ protected function setUp(): void $this->monitor = new ChainedMonitor(); } - /** - * @testdox The chained monitor forwards calls to all attached monitors - */ + #[TestDox('The chained monitor forwards calls to all attached monitors')] public function testChaining() { $monitor1 = $this->createMonitor(); diff --git a/Tests/Monitor/DebugMonitorTest.php b/Tests/Monitor/DebugMonitorTest.php index 7e9e31a6..accbc57c 100644 --- a/Tests/Monitor/DebugMonitorTest.php +++ b/Tests/Monitor/DebugMonitorTest.php @@ -7,6 +7,7 @@ namespace Joomla\Database\Tests\Monitor; use Joomla\Database\Monitor\DebugMonitor; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; /** @@ -35,9 +36,7 @@ protected function setUp(): void $this->monitor = new DebugMonitor(); } - /** - * @testdox The monitor collects debug metrics about a query - */ + #[TestDox('The monitor collects debug metrics about a query')] public function testMonitor() { // "Execute" 3 queries, we'll use the password_hash function to force time/memory usage to increase along the way diff --git a/Tests/Monitor/LoggingMonitorTest.php b/Tests/Monitor/LoggingMonitorTest.php index 5465e31a..ada37039 100644 --- a/Tests/Monitor/LoggingMonitorTest.php +++ b/Tests/Monitor/LoggingMonitorTest.php @@ -7,6 +7,7 @@ namespace Joomla\Database\Tests\Monitor; use Joomla\Database\Monitor\LoggingMonitor; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; use ColinODell\PsrTestLogger\TestLogger; @@ -45,9 +46,7 @@ protected function setUp(): void $this->monitor = new LoggingMonitor(); } - /** - * @testdox The monitor does not log messages if no logger is injected - */ + #[TestDox('The monitor does not log messages if no logger is injected')] public function testStartQueryNoLogger() { $this->monitor->startQuery('SELECT 1'); @@ -57,9 +56,7 @@ public function testStartQueryNoLogger() ); } - /** - * @testdox The monitor does log messages if a logger is injected - */ + #[TestDox('The monitor does log messages if a logger is injected')] public function testStartQueryWithLogger() { $this->monitor->setLogger($this->logger); diff --git a/Tests/Mysql/MysqlDriverTest.php b/Tests/Mysql/MysqlDriverTest.php index feae9357..40499c00 100644 --- a/Tests/Mysql/MysqlDriverTest.php +++ b/Tests/Mysql/MysqlDriverTest.php @@ -15,10 +15,13 @@ use Joomla\Database\ParameterType; use Joomla\Database\Tests\AbstractDatabaseDriverTestCase; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\Attributes\TestDox; /** * Test class for Joomla\Database\Mysql\MysqlDriver */ +#[RequiresPhpExtension('pdo_mysql')] class MysqlDriverTest extends AbstractDatabaseDriverTestCase { /** @@ -41,7 +44,7 @@ public static function setUpBeforeClass(): void parent::setUpBeforeClass(); - if (!static::$connection || static::$connection->getName() !== 'mysql') { + if (!static::$connection) { self::markTestSkipped('MySQL database not configured.'); } } @@ -96,14 +99,6 @@ protected function tearDown(): void */ public static function dataGetTableColumns(): array { - // For unknown reasons, the connection gets lost on Travis. re-establish, if that happens - if (static::$connection === null) { - self::setUpBeforeClass(); - } - - $isMySQL8 = !static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '8.0', '>='); - $useDisplayWidth = static::$connection->isMariaDb() || version_compare(static::$connection->getVersion(), '8.0.17', '<'); - return [ 'only column types' => [ '#__dbtest', @@ -123,11 +118,11 @@ public static function dataGetTableColumns(): array [ 'id' => (object) [ 'Field' => 'id', - 'Type' => $useDisplayWidth ? 'int(10) unsigned' : 'int unsigned', - 'Collation' => $isMySQL8 ? null : '', + 'Type' => '<<>>', + 'Collation' => null, 'Null' => 'NO', 'Key' => 'PRI', - 'Default' => $isMySQL8 ? null : '', + 'Default' => null, 'Extra' => 'auto_increment', 'Privileges' => 'select,insert,update,references', 'Comment' => '', @@ -135,10 +130,10 @@ public static function dataGetTableColumns(): array 'title' => (object) [ 'Field' => 'title', 'Type' => 'varchar(50)', - 'Collation' => $isMySQL8 ? 'utf8mb3_general_ci' : 'utf8_general_ci', + 'Collation' => '<<>>', 'Null' => 'NO', 'Key' => '', - 'Default' => $isMySQL8 ? null : '', + 'Default' => '<<>>', 'Extra' => '', 'Privileges' => 'select,insert,update,references', 'Comment' => '', @@ -157,10 +152,10 @@ public static function dataGetTableColumns(): array 'description' => (object) [ 'Field' => 'description', 'Type' => 'text', - 'Collation' => $isMySQL8 ? 'utf8mb3_general_ci' : 'utf8_general_ci', + 'Collation' => '<<>>', 'Null' => 'NO', 'Key' => '', - 'Default' => $isMySQL8 ? null : '', + 'Default' => '<<>>', 'Extra' => '', 'Privileges' => 'select,insert,update,references', 'Comment' => '', @@ -242,13 +237,46 @@ public static function dataQuoteName(): array * Overrides for parent class test cases */ + /** + * @param string $table The name of the database table. + * @param boolean $typeOnly True (default) to only return field types. + * @param array $expected Expected result. + */ + #[DataProvider('dataGetTableColumns')] + #[TestDox('Information about the columns of a database table is returned')] + public function testGetTableColumns(string $table, bool $typeOnly, array $expected) + { + if (!$typeOnly) { + $useDisplayWidth = static::$connection->isMariaDb() || version_compare(static::$connection->getVersion(), '8.0.17', '<'); + + $collationText = match (true) { + !static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '8.0.30', '>=') => 'utf8mb3_general_ci', + static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '11.5', '>=') => 'utf8mb3_uca1400_ai_ci', + static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '10.6', '>=') => 'utf8mb3_general_ci', + default => 'utf8_general_ci', + }; + + $defaultText = match (true) { + !static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '8.0', '>=') => null, + static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '11.5', '>=') => null, + default => '', + }; + + $expected['id']->Type = $useDisplayWidth ? 'int(10) unsigned' : 'int unsigned'; + $expected['title']->Collation = $collationText; + $expected['title']->Default = $defaultText; + $expected['description']->Collation = $collationText; + $expected['description']->Default = $defaultText; + } + + parent::testGetTableColumns($table, $typeOnly, $expected); + } + /* * Test cases for this subclass */ - /** - * @testdox The database driver reports if it is supported in the present environment - */ + #[TestDox('The database driver reports if it is supported in the present environment')] public function testIsSupported() { $this->assertTrue( @@ -256,9 +284,7 @@ public function testIsSupported() ); } - /** - * @testdox The database collation can be retrieved - */ + #[TestDox('The database collation can be retrieved')] public function testGetCollation() { $this->assertNotFalse( @@ -266,9 +292,7 @@ public function testGetCollation() ); } - /** - * @testdox The database connection collation can be retrieved - */ + #[TestDox('The database connection collation can be retrieved')] public function testGetConnectionCollation() { $this->assertNotFalse( @@ -276,9 +300,7 @@ public function testGetConnectionCollation() ); } - /** - * @testdox The database connection encryption can be retrieved - */ + #[TestDox('The database connection encryption can be retrieved')] public function testGetConnectionEncryption() { $this->assertEmpty( @@ -287,9 +309,7 @@ public function testGetConnectionEncryption() ); } - /** - * @testdox A list of queries to create the given tables is returned - */ + #[TestDox('A list of queries to create the given tables is returned')] public function testGetTableCreate() { $this->assertCount( @@ -299,9 +319,7 @@ public function testGetTableCreate() ); } - /** - * @testdox Information about the keys of a database table is returned - */ + #[TestDox('Information about the keys of a database table is returned')] public function testGetTableKeys() { $dbtestPrimaryKey = [ @@ -320,10 +338,24 @@ public function testGetTableKeys() 'Index_comment' => '', ]; - // MySQL 8.0 adds additional data + // MySQL 8.0 adds additional data and casts certain keys to integers if (!static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '8.0', '>=')) { + $dbtestPrimaryKey['Non_unique'] = (int) $dbtestPrimaryKey['Non_unique']; + $dbtestPrimaryKey['Seq_in_index'] = (int) $dbtestPrimaryKey['Seq_in_index']; + $dbtestPrimaryKey['Cardinality'] = (int) $dbtestPrimaryKey['Cardinality']; + $dbtestPrimaryKey['Visible'] = 'YES'; - $dbtestPrimaryKey['Expression'] = null; + if (version_compare(static::$connection->getVersion(), '8.0.13', '>=')) { + $dbtestPrimaryKey['Expression'] = null; + } + + // MariaDB 10.6 adds additional data and casts certain keys to integers + } elseif (static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '10.6', '>=')) { + $dbtestPrimaryKey['Non_unique'] = (int) $dbtestPrimaryKey['Non_unique']; + $dbtestPrimaryKey['Seq_in_index'] = (int) $dbtestPrimaryKey['Seq_in_index']; + $dbtestPrimaryKey['Cardinality'] = (int) $dbtestPrimaryKey['Cardinality']; + + $dbtestPrimaryKey['Ignored'] = 'NO'; } $keys = [ @@ -336,9 +368,7 @@ public function testGetTableKeys() ); } - /** - * @testdox The database reports if it has support for the utf8mb4 character sets - */ + #[TestDox('The database reports if it has support for the utf8mb4 character sets')] public function testHasUTF8mb4Support() { $this->assertFalse( @@ -347,9 +377,7 @@ public function testHasUTF8mb4Support() ); } - /** - * @testdox A transaction can be started and committed - */ + #[TestDox('A transaction can be started and committed')] public function testTransactionCommit() { $this->loadExampleData(); @@ -404,12 +432,11 @@ public static function dataTransactionRollback(): array } /** - * @testdox A transaction can be started and committed - * * @param string|null $toSavepoint Savepoint name to rollback transaction to * @param integer $tupleCount Number of tuples found after insertion and rollback */ #[DataProvider('dataTransactionRollback')] + #[TestDox('A transaction can be started and committed')] public function testTransactionRollback(?string $toSavepoint, int $tupleCount) { $this->loadExampleData(); @@ -477,9 +504,7 @@ public function testTransactionRollback(?string $toSavepoint, int $tupleCount) $this->assertCount($tupleCount, $transactionRows); } - /** - * @testdox The database connection can be retrieved - */ + #[TestDox('The database connection can be retrieved')] public function testGetConnection() { $this->assertInstanceOf( @@ -488,9 +513,7 @@ public function testGetConnection() ); } - /** - * @testdox The name of the database driver is retrieved - */ + #[TestDox('The name of the database driver is retrieved')] public function testGetName() { $this->assertSame( @@ -499,9 +522,7 @@ public function testGetName() ); } - /** - * @testdox The type of server for the database driver is retrieved - */ + #[TestDox('The type of server for the database driver is retrieved')] public function testGetServerType() { $this->assertSame( @@ -510,9 +531,7 @@ public function testGetServerType() ); } - /** - * @testdox The null date for the server type is retrieved - */ + #[TestDox('The null date for the server type is retrieved')] public function testGetNullDate() { $result = static::$connection->setQuery('SELECT @@SESSION.sql_mode;')->loadResult(); @@ -528,9 +547,7 @@ public function testGetNullDate() ); } - /** - * @testdox An exporter for the database driver can be created - */ + #[TestDox('An exporter for the database driver can be created')] public function testGetExporter() { $this->assertInstanceOf( @@ -539,9 +556,7 @@ public function testGetExporter() ); } - /** - * @testdox An importer for the database driver can be created - */ + #[TestDox('An importer for the database driver can be created')] public function testGetImporter() { $this->assertInstanceOf( @@ -550,9 +565,7 @@ public function testGetImporter() ); } - /** - * @testdox A new query instance can be created - */ + #[TestDox('A new query instance can be created')] public function testGetQueryNewInstance() { $this->assertInstanceOf( @@ -561,9 +574,7 @@ public function testGetQueryNewInstance() ); } - /** - * @testdox Binary values are correctly supported - */ + #[TestDox('Binary values are correctly supported')] public function testQuoteAndDecodeBinary() { $this->loadExampleData(); @@ -650,9 +661,7 @@ public function testQuoteAndDecodeBinary() $this->assertEquals($expected, $result); } - /** - * @testdox The connection can be set to use UTF-8 encoding - */ + #[TestDox('The connection can be set to use UTF-8 encoding')] public function testSetUtf() { $this->assertFalse( @@ -660,9 +669,7 @@ public function testSetUtf() ); } - /** - * @testdox A database table can be truncated - */ + #[TestDox('A database table can be truncated')] public function testTruncateTable() { $this->loadExampleData(); diff --git a/Tests/Mysql/MysqlExporterTest.php b/Tests/Mysql/MysqlExporterTest.php index f7c4488f..1f20d78a 100644 --- a/Tests/Mysql/MysqlExporterTest.php +++ b/Tests/Mysql/MysqlExporterTest.php @@ -11,7 +11,8 @@ use Joomla\Database\Mysql\MysqlExporter; use Joomla\Database\Mysql\MysqlQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -22,7 +23,7 @@ class MysqlExporterTest extends TestCase /** * Mock database driver * - * @var MockObject|MysqlDriver + * @var Stub|MysqlDriver */ private $db; @@ -37,20 +38,17 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(MysqlDriver::class); + $this->db = $this->createStub(MysqlDriver::class); - $this->db->expects($this->any()) - ->method('getPrefix') + $this->db->method('getPrefix') ->willReturn('jos_'); - $this->db->expects($this->any()) - ->method('createQuery') + $this->db->method('createQuery') ->willReturnCallback(function () { return new MysqlQuery($this->db); }); - $this->db->expects($this->any()) - ->method('getTableColumns') + $this->db->method('getTableColumns') ->willReturn( [ 'id' => (object) [ @@ -78,8 +76,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('getTableKeys') + $this->db->method('getTableKeys') ->willReturn( [ (object) [ @@ -99,8 +96,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('quoteName') + $this->db->method('quoteName') ->willReturnCallback( function ($name, $as = null) { if (is_string($name)) { @@ -207,13 +203,12 @@ public static function dataCastingToString(): array } /** - * @testdox The exporter can be cast to a string - * * @param boolean $withStructure True to export the structure, false to not. * @param boolean $withData True to export the data, false to not. * @param string $expectedXml Expected XML string. */ #[DataProvider('dataCastingToString')] + #[TestDox('The exporter can be cast to a string')] public function testCastingToString(bool $withStructure, bool $withData, string $expectedXml) { $exporter = new MysqlExporter(); @@ -224,8 +219,7 @@ public function testCastingToString(bool $withStructure, bool $withData, string ->withData($withData); if ($withData) { - $this->db->expects($this->once()) - ->method('loadObjectList') + $this->db->method('loadObjectList') ->willReturn( [ (object) [ @@ -278,13 +272,12 @@ public static function dataCheck(): array } /** - * @testdox The exporter checks for errors - * * @param string|null $db Database driver to set in the exporter. * @param string[]|string|null $from Database tables to export from. * @param string|null $exceptionMessage If an Exception should be thrown, the expected message */ #[DataProvider('dataCheck')] + #[TestDox('The exporter checks for errors')] public function testCheck(?string $db, $from, ?string $exceptionMessage) { if ($exceptionMessage) { @@ -295,7 +288,7 @@ public function testCheck(?string $db, $from, ?string $exceptionMessage) $exporter = new MysqlExporter(); if ($db) { - $exporter->setDbo($this->createMock($db)); + $exporter->setDbo($this->createStub($db)); } if ($from) { diff --git a/Tests/Mysql/MysqlImporterTest.php b/Tests/Mysql/MysqlImporterTest.php index 512d4439..98805898 100644 --- a/Tests/Mysql/MysqlImporterTest.php +++ b/Tests/Mysql/MysqlImporterTest.php @@ -11,7 +11,8 @@ use Joomla\Database\Mysql\MysqlImporter; use Joomla\Database\Mysql\MysqlQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -22,7 +23,7 @@ class MysqlImporterTest extends TestCase /** * Mock database driver * - * @var MockObject|MysqlDriver + * @var Stub|MysqlDriver */ private $db; @@ -63,20 +64,17 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(MysqlDriver::class); + $this->db = $this->createStub(MysqlDriver::class); - $this->db->expects($this->any()) - ->method('getPrefix') + $this->db->method('getPrefix') ->willReturn('jos_'); - $this->db->expects($this->any()) - ->method('createQuery') + $this->db->method('createQuery') ->willReturnCallback(function () { return new MysqlQuery($this->db); }); - $this->db->expects($this->any()) - ->method('getTableColumns') + $this->db->method('getTableColumns') ->willReturn( [ 'id' => (object) [ @@ -104,8 +102,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('getTableKeys') + $this->db->method('getTableKeys') ->willReturn( [ (object) [ @@ -125,16 +122,14 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('getTableList') + $this->db->method('getTableList') ->willReturn( [ 'jos_dbtest', ] ); - $this->db->expects($this->any()) - ->method('insertObject') + $this->db->method('insertObject') ->willReturnCallback( function ($table, &$object, $key = null) { if (!isset($this->executedInsertObjects[$table])) { @@ -147,8 +142,7 @@ function ($table, &$object, $key = null) { } ); - $this->db->expects($this->any()) - ->method('quoteName') + $this->db->method('quoteName') ->willReturnCallback( function ($name, $as = null) { if (is_string($name)) { @@ -165,8 +159,7 @@ function ($name, $as = null) { } ); - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback( function ($text, $escape = true) { if (is_string($text)) { @@ -183,8 +176,7 @@ function ($text, $escape = true) { } ); - $this->db->expects($this->any()) - ->method('setQuery') + $this->db->method('setQuery') ->willReturnCallback( function ($query, $offset = 0, $limit = 0) { $this->executedQueries[] = $query; @@ -199,7 +191,7 @@ function ($query, $offset = 0, $limit = 0) { */ protected function tearDown(): void { - $this->expectedInsertObjects = []; + $this->executedInsertObjects = []; $this->executedQueries = []; } @@ -304,8 +296,6 @@ public static function dataImport(): array } /** - * @testdox The importer processes a XML document - * * @param boolean $mergeStructure True to merge the structure. * @param boolean $importData True to import the data. * @param \SimpleXMLElement $from XML document to import. @@ -313,6 +303,7 @@ public static function dataImport(): array * @param string[] $expectedInsertObjects The expected objects to be given to the database's insertObject method. */ #[DataProvider('dataImport')] + #[TestDox('The importer processes a XML document')] public function testImport(bool $mergeStructure, bool $importData, \SimpleXMLElement $from, array $expectedQueries, array $expectedInsertObjects) { $importer = new MysqlImporter(); @@ -366,13 +357,12 @@ public static function dataCheck(): array } /** - * @testdox The importer checks for errors - * * @param string|null $db Database driver to set in the importer. * @param string[]|string|null $from Database structure to import. * @param string|null $exceptionMessage If an Exception should be thrown, the expected message */ #[DataProvider('dataCheck')] + #[TestDox('The importer checks for errors')] public function testCheck(?string $db, $from, ?string $exceptionMessage) { if ($exceptionMessage) { @@ -383,7 +373,7 @@ public function testCheck(?string $db, $from, ?string $exceptionMessage) $importer = new MysqlImporter(); if ($db) { - $importer->setDbo($this->createMock($db)); + $importer->setDbo($this->createStub($db)); } if ($from) { diff --git a/Tests/Mysql/MysqlPreparedStatementTest.php b/Tests/Mysql/MysqlPreparedStatementTest.php index f450db22..62eaaa0c 100644 --- a/Tests/Mysql/MysqlPreparedStatementTest.php +++ b/Tests/Mysql/MysqlPreparedStatementTest.php @@ -9,7 +9,10 @@ use Joomla\Database\DatabaseDriver; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Test\DatabaseTestCase; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +#[RequiresPhpExtension('pdo_mysql')] class MysqlPreparedStatementTest extends DatabaseTestCase { /** @@ -21,7 +24,7 @@ public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); - if (!static::$connection || static::$connection->getName() !== 'mysql') { + if (!static::$connection) { self::markTestSkipped('MySQL database not configured.'); } } @@ -66,9 +69,8 @@ protected function tearDown(): void /** * Make sure the mysqli driver correctly runs queries with named parameters appearing more than once. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testPreparedStatementWithDuplicateKey() { $dummyValue = 'test'; @@ -86,9 +88,8 @@ public function testPreparedStatementWithDuplicateKey() /** * Regression test to ensure running queries with named parameters appearing once didn't break. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testPreparedStatementWithSingleKey() { $dummyValue = 'test'; diff --git a/Tests/Mysql/MysqlQueryTest.php b/Tests/Mysql/MysqlQueryTest.php index a9d96c62..861236b8 100644 --- a/Tests/Mysql/MysqlQueryTest.php +++ b/Tests/Mysql/MysqlQueryTest.php @@ -9,7 +9,8 @@ use Joomla\Database\DatabaseInterface; use Joomla\Database\Mysql\MysqlQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -27,7 +28,7 @@ class MysqlQueryTest extends TestCase /** * Mock database driver * - * @var MockObject|DatabaseInterface + * @var Stub|DatabaseInterface */ private $db; @@ -42,7 +43,7 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(DatabaseInterface::class); + $this->db = $this->createStub(DatabaseInterface::class); $this->query = new MysqlQuery($this->db); } @@ -60,17 +61,15 @@ public static function dataConcatenate(): array } /** - * @testdox A SQL statement for concatenating values is generated - * * @param string[] $values An array of values to concatenate. * @param string|null $separator As separator to place between each value. * @param string $expected The expected query string. */ #[DataProvider('dataConcatenate')] + #[TestDox('A SQL statement for concatenating values is generated')] public function testConcatenate(array $values, ?string $separator, string $expected) { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); @@ -81,9 +80,7 @@ public function testConcatenate(array $values, ?string $separator, string $expec ); } - /** - * @testdox A SQL statement for the MySQL find_in_set() function is generated - */ + #[TestDox('A SQL statement for the MySQL find_in_set() function is generated')] public function testFindInSet() { $this->assertSame( @@ -92,13 +89,10 @@ public function testFindInSet() ); } - /** - * @testdox A SQL statement to concatenate a group of values is generated - */ + #[TestDox('A SQL statement to concatenate a group of values is generated')] public function testGroupConcat() { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); @@ -109,9 +103,7 @@ public function testGroupConcat() ); } - /** - * @testdox A SQL statement to get a random floating point value is generated - */ + #[TestDox('A SQL statement to get a random floating point value is generated')] public function testRand() { $this->assertSame( @@ -120,9 +112,7 @@ public function testRand() ); } - /** - * @testdox A SQL statement to prepend a string with a regex operator is generated - */ + #[TestDox('A SQL statement to prepend a string with a regex operator is generated')] public function testRegexp() { $this->assertSame( @@ -131,17 +121,13 @@ public function testRegexp() ); } - /** - * @testdox A string is cast as a character string for the driver - */ + #[TestDox('A string is cast as a character string for the driver')] public function testCastAsWithChar() { $this->assertSame('123', $this->query->castAs('CHAR', '123')); } - /** - * @testdox The length param is added to the CAST statement when provided - */ + #[TestDox('The length param is added to the CAST statement when provided')] public function testCastAsWithCharAndLengthParam() { $this->assertSame( @@ -150,9 +136,7 @@ public function testCastAsWithCharAndLengthParam() ); } - /** - * @testdox Test castAs behaviour with INT (adds 0 to the input) - */ + #[TestDox('Test castAs behaviour with INT (adds 0 to the input)')] public function testCastAsWithIntegerType() { $this->assertSame( diff --git a/Tests/Mysqli/MysqliDriverTest.php b/Tests/Mysqli/MysqliDriverTest.php index 59d5d33d..7bcb5ba5 100644 --- a/Tests/Mysqli/MysqliDriverTest.php +++ b/Tests/Mysqli/MysqliDriverTest.php @@ -16,10 +16,13 @@ use Joomla\Database\ParameterType; use Joomla\Database\Tests\AbstractDatabaseDriverTestCase; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\Attributes\TestDox; /** * Test class for Joomla\Database\Mysqli\MysqliDriver */ +#[RequiresPhpExtension('mysqli')] class MysqliDriverTest extends AbstractDatabaseDriverTestCase { /** @@ -46,7 +49,7 @@ public static function setUpBeforeClass(): void parent::setUpBeforeClass(); - if (!static::$connection || static::$connection->getName() !== 'mysqli') { + if (!static::$connection) { self::markTestSkipped('MySQL database not configured.'); } } @@ -115,14 +118,6 @@ public static function dataEscape(): array */ public static function dataGetTableColumns(): array { - // For unknown reasons, the connection gets lost on Travis. re-establish, if that happens - if (static::$connection === null) { - self::setUpBeforeClass(); - } - - $isMySQL8 = !static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '8.0', '>='); - $useDisplayWidth = static::$connection->isMariaDb() || version_compare(static::$connection->getVersion(), '8.0.17', '<'); - return [ 'only column types' => [ '#__dbtest', @@ -142,11 +137,11 @@ public static function dataGetTableColumns(): array [ 'id' => (object) [ 'Field' => 'id', - 'Type' => $useDisplayWidth ? 'int(10) unsigned' : 'int unsigned', - 'Collation' => $isMySQL8 ? null : '', + 'Type' => '<<>>', + 'Collation' => null, 'Null' => 'NO', 'Key' => 'PRI', - 'Default' => $isMySQL8 ? null : '', + 'Default' => null, 'Extra' => 'auto_increment', 'Privileges' => 'select,insert,update,references', 'Comment' => '', @@ -154,10 +149,10 @@ public static function dataGetTableColumns(): array 'title' => (object) [ 'Field' => 'title', 'Type' => 'varchar(50)', - 'Collation' => $isMySQL8 ? 'utf8mb3_general_ci' : 'utf8_general_ci', + 'Collation' => '<<>>', 'Null' => 'NO', 'Key' => '', - 'Default' => $isMySQL8 ? null : '', + 'Default' => '<<>>', 'Extra' => '', 'Privileges' => 'select,insert,update,references', 'Comment' => '', @@ -176,10 +171,10 @@ public static function dataGetTableColumns(): array 'description' => (object) [ 'Field' => 'description', 'Type' => 'text', - 'Collation' => $isMySQL8 ? 'utf8mb3_general_ci' : 'utf8_general_ci', + 'Collation' => '<<>>', 'Null' => 'NO', 'Key' => '', - 'Default' => $isMySQL8 ? null : '', + 'Default' => '<<>>', 'Extra' => '', 'Privileges' => 'select,insert,update,references', 'Comment' => '', @@ -246,13 +241,46 @@ public static function dataQuoteName(): array * Overrides for parent class test cases */ + /** + * @param string $table The name of the database table. + * @param boolean $typeOnly True (default) to only return field types. + * @param array $expected Expected result. + */ + #[DataProvider('dataGetTableColumns')] + #[TestDox('Information about the columns of a database table is returned')] + public function testGetTableColumns(string $table, bool $typeOnly, array $expected) + { + if (!$typeOnly) { + $useDisplayWidth = static::$connection->isMariaDb() || version_compare(static::$connection->getVersion(), '8.0.17', '<'); + + $collationText = match (true) { + !static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '8.0.30', '>=') => 'utf8mb3_general_ci', + static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '11.5', '>=') => 'utf8mb3_uca1400_ai_ci', + static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '10.6', '>=') => 'utf8mb3_general_ci', + default => 'utf8_general_ci', + }; + + $defaultText = match (true) { + !static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '8.0', '>=') => null, + static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '11.5', '>=') => null, + default => '', + }; + + $expected['id']->Type = $useDisplayWidth ? 'int(10) unsigned' : 'int unsigned'; + $expected['title']->Collation = $collationText; + $expected['title']->Default = $defaultText; + $expected['description']->Collation = $collationText; + $expected['description']->Default = $defaultText; + } + + parent::testGetTableColumns($table, $typeOnly, $expected); + } + /* * Test cases for this subclass */ - /** - * @testdox The database driver reports if it is supported in the present environment - */ + #[TestDox('The database driver reports if it is supported in the present environment')] public function testIsSupported() { $this->assertTrue( @@ -260,9 +288,7 @@ public function testIsSupported() ); } - /** - * @testdox The database collation can be retrieved - */ + #[TestDox('The database collation can be retrieved')] public function testGetCollation() { $this->assertNotFalse( @@ -270,9 +296,7 @@ public function testGetCollation() ); } - /** - * @testdox The database connection collation can be retrieved - */ + #[TestDox('The database connection collation can be retrieved')] public function testGetConnectionCollation() { $this->assertNotFalse( @@ -280,9 +304,7 @@ public function testGetConnectionCollation() ); } - /** - * @testdox The database connection encryption can be retrieved - */ + #[TestDox('The database connection encryption can be retrieved')] public function testGetConnectionEncryption() { $this->assertEmpty( @@ -291,9 +313,7 @@ public function testGetConnectionEncryption() ); } - /** - * @testdox A list of queries to create the given tables is returned - */ + #[TestDox('A list of queries to create the given tables is returned')] public function testGetTableCreate() { $this->assertCount( @@ -303,9 +323,7 @@ public function testGetTableCreate() ); } - /** - * @testdox Information about the keys of a database table is returned - */ + #[TestDox('Information about the keys of a database table is returned')] public function testGetTableKeys() { $dbtestPrimaryKey = [ @@ -331,7 +349,17 @@ public function testGetTableKeys() $dbtestPrimaryKey['Cardinality'] = (int) $dbtestPrimaryKey['Cardinality']; $dbtestPrimaryKey['Visible'] = 'YES'; - $dbtestPrimaryKey['Expression'] = null; + if (version_compare(static::$connection->getVersion(), '8.0.13', '>=')) { + $dbtestPrimaryKey['Expression'] = null; + } + + // MariaDB 10.6 adds additional data and casts certain keys to integers + } elseif (static::$connection->isMariaDb() && version_compare(static::$connection->getVersion(), '10.6', '>=')) { + $dbtestPrimaryKey['Non_unique'] = (int) $dbtestPrimaryKey['Non_unique']; + $dbtestPrimaryKey['Seq_in_index'] = (int) $dbtestPrimaryKey['Seq_in_index']; + $dbtestPrimaryKey['Cardinality'] = (int) $dbtestPrimaryKey['Cardinality']; + + $dbtestPrimaryKey['Ignored'] = 'NO'; } $keys = [ @@ -344,9 +372,7 @@ public function testGetTableKeys() ); } - /** - * @testdox The database reports if it has support for the utf8mb4 character sets - */ + #[TestDox('The database reports if it has support for the utf8mb4 character sets')] public function testHasUTF8mb4Support() { $this->assertTrue( @@ -355,9 +381,7 @@ public function testHasUTF8mb4Support() ); } - /** - * @testdox A transaction can be started and committed - */ + #[TestDox('A transaction can be started and committed')] public function testTransactionCommit() { $this->loadExampleData(); @@ -412,12 +436,11 @@ public static function dataTransactionRollback(): array } /** - * @testdox A transaction can be started and committed - * * @param string|null $toSavepoint Savepoint name to rollback transaction to * @param integer $tupleCount Number of tuples found after insertion and rollback */ #[DataProvider('dataTransactionRollback')] + #[TestDox('A transaction can be started and committed')] public function testTransactionRollback(?string $toSavepoint, int $tupleCount) { $this->loadExampleData(); @@ -485,9 +508,7 @@ public function testTransactionRollback(?string $toSavepoint, int $tupleCount) $this->assertCount($tupleCount, $transactionRows); } - /** - * @testdox The null date for the server type is retrieved - */ + #[TestDox('The null date for the server type is retrieved')] public function testGetNullDate() { $result = static::$connection->setQuery('SELECT @@SESSION.sql_mode;')->loadResult(); @@ -503,9 +524,7 @@ public function testGetNullDate() ); } - /** - * @testdox The database connection can be retrieved - */ + #[TestDox('The database connection can be retrieved')] public function testGetConnection() { $this->assertInstanceOf( @@ -514,9 +533,7 @@ public function testGetConnection() ); } - /** - * @testdox The name of the database driver is retrieved - */ + #[TestDox('The name of the database driver is retrieved')] public function testGetName() { $this->assertSame( @@ -525,9 +542,7 @@ public function testGetName() ); } - /** - * @testdox The type of server for the database driver is retrieved - */ + #[TestDox('The type of server for the database driver is retrieved')] public function testGetServerType() { $this->assertSame( @@ -536,9 +551,7 @@ public function testGetServerType() ); } - /** - * @testdox An exporter for the database driver can be created - */ + #[TestDox('An exporter for the database driver can be created')] public function testGetExporter() { $this->assertInstanceOf( @@ -547,9 +560,7 @@ public function testGetExporter() ); } - /** - * @testdox An importer for the database driver can be created - */ + #[TestDox('An importer for the database driver can be created')] public function testGetImporter() { $this->assertInstanceOf( @@ -558,9 +569,7 @@ public function testGetImporter() ); } - /** - * @testdox A new query instance can be created - */ + #[TestDox('A new query instance can be created')] public function testGetQueryNewInstance() { $this->assertInstanceOf( @@ -569,9 +578,7 @@ public function testGetQueryNewInstance() ); } - /** - * @testdox Binary values are correctly supported - */ + #[TestDox('Binary values are correctly supported')] public function testQuoteAndDecodeBinary() { $this->loadExampleData(); diff --git a/Tests/Mysqli/MysqliExporterTest.php b/Tests/Mysqli/MysqliExporterTest.php index 9059f3fd..3f3b2d3b 100644 --- a/Tests/Mysqli/MysqliExporterTest.php +++ b/Tests/Mysqli/MysqliExporterTest.php @@ -11,7 +11,8 @@ use Joomla\Database\Mysqli\MysqliExporter; use Joomla\Database\Mysqli\MysqliQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -22,7 +23,7 @@ class MysqliExporterTest extends TestCase /** * Mock database driver * - * @var MockObject|MysqliDriver + * @var Stub|MysqliDriver */ private $db; @@ -37,20 +38,17 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(MysqliDriver::class); + $this->db = $this->createStub(MysqliDriver::class); - $this->db->expects($this->any()) - ->method('getPrefix') + $this->db->method('getPrefix') ->willReturn('jos_'); - $this->db->expects($this->any()) - ->method('createQuery') + $this->db->method('createQuery') ->willReturnCallback(function () { return new MysqliQuery($this->db); }); - $this->db->expects($this->any()) - ->method('getTableColumns') + $this->db->method('getTableColumns') ->willReturn( [ 'id' => (object) [ @@ -78,8 +76,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('getTableKeys') + $this->db->method('getTableKeys') ->willReturn( [ (object) [ @@ -99,8 +96,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('quoteName') + $this->db->method('quoteName') ->willReturnCallback( function ($name, $as = null) { if (is_string($name)) { @@ -207,13 +203,12 @@ public static function dataCastingToString(): array } /** - * @testdox The exporter can be cast to a string - * * @param boolean $withStructure True to export the structure, false to not. * @param boolean $withData True to export the data, false to not. * @param string $expectedXml Expected XML string. */ #[DataProvider('dataCastingToString')] + #[TestDox('The exporter can be cast to a string')] public function testCastingToString(bool $withStructure, bool $withData, string $expectedXml) { $exporter = new MysqliExporter(); @@ -224,8 +219,7 @@ public function testCastingToString(bool $withStructure, bool $withData, string ->withData($withData); if ($withData) { - $this->db->expects($this->once()) - ->method('loadObjectList') + $this->db->method('loadObjectList') ->willReturn( [ (object) [ @@ -278,13 +272,12 @@ public static function dataCheck(): array } /** - * @testdox The exporter checks for errors - * * @param string|null $db Database driver to set in the exporter. * @param string[]|string|null $from Database tables to export from. * @param string|null $exceptionMessage If an Exception should be thrown, the expected message */ #[DataProvider('dataCheck')] + #[TestDox('The exporter checks for errors')] public function testCheck(?string $db, $from, ?string $exceptionMessage) { if ($exceptionMessage) { @@ -295,7 +288,7 @@ public function testCheck(?string $db, $from, ?string $exceptionMessage) $exporter = new MysqliExporter(); if ($db) { - $exporter->setDbo($this->createMock($db)); + $exporter->setDbo($this->createStub($db)); } if ($from) { diff --git a/Tests/Mysqli/MysqliImporterTest.php b/Tests/Mysqli/MysqliImporterTest.php index b60f457d..7e24354c 100644 --- a/Tests/Mysqli/MysqliImporterTest.php +++ b/Tests/Mysqli/MysqliImporterTest.php @@ -11,7 +11,8 @@ use Joomla\Database\Mysqli\MysqliImporter; use Joomla\Database\Mysqli\MysqliQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -22,7 +23,7 @@ class MysqliImporterTest extends TestCase /** * Mock database driver * - * @var MockObject|MysqliDriver + * @var Stub|MysqliDriver */ private $db; @@ -63,20 +64,17 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(MysqliDriver::class); + $this->db = $this->createStub(MysqliDriver::class); - $this->db->expects($this->any()) - ->method('getPrefix') + $this->db->method('getPrefix') ->willReturn('jos_'); - $this->db->expects($this->any()) - ->method('createQuery') + $this->db->method('createQuery') ->willReturnCallback(function () { return new MysqliQuery($this->db); }); - $this->db->expects($this->any()) - ->method('getTableColumns') + $this->db->method('getTableColumns') ->willReturn( [ 'id' => (object) [ @@ -104,8 +102,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('getTableKeys') + $this->db->method('getTableKeys') ->willReturn( [ (object) [ @@ -125,16 +122,14 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('getTableList') + $this->db->method('getTableList') ->willReturn( [ 'jos_dbtest', ] ); - $this->db->expects($this->any()) - ->method('insertObject') + $this->db->method('insertObject') ->willReturnCallback( function ($table, &$object, $key = null) { if (!isset($this->executedInsertObjects[$table])) { @@ -147,8 +142,7 @@ function ($table, &$object, $key = null) { } ); - $this->db->expects($this->any()) - ->method('quoteName') + $this->db->method('quoteName') ->willReturnCallback( function ($name, $as = null) { if (is_string($name)) { @@ -165,8 +159,7 @@ function ($name, $as = null) { } ); - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback( function ($text, $escape = true) { if (is_string($text)) { @@ -183,8 +176,7 @@ function ($text, $escape = true) { } ); - $this->db->expects($this->any()) - ->method('setQuery') + $this->db->method('setQuery') ->willReturnCallback( function ($query, $offset = 0, $limit = 0) { $this->executedQueries[] = $query; @@ -199,7 +191,7 @@ function ($query, $offset = 0, $limit = 0) { */ protected function tearDown(): void { - $this->expectedInsertObjects = []; + $this->executedInsertObjects = []; $this->executedQueries = []; } @@ -304,8 +296,6 @@ public static function dataImport(): array } /** - * @testdox The importer processes a XML document - * * @param boolean $mergeStructure True to merge the structure. * @param boolean $importData True to import the data. * @param \SimpleXMLElement $from XML document to import. @@ -313,6 +303,7 @@ public static function dataImport(): array * @param string[] $expectedInsertObjects The expected objects to be given to the database's insertObject method. */ #[DataProvider('dataImport')] + #[TestDox('The importer processes a XML document')] public function testImport(bool $mergeStructure, bool $importData, \SimpleXMLElement $from, array $expectedQueries, array $expectedInsertObjects) { $importer = new MysqliImporter(); @@ -366,13 +357,12 @@ public static function dataCheck(): array } /** - * @testdox The importer checks for errors - * * @param string|null $db Database driver to set in the importer. * @param string[]|string|null $from Database structure to import. * @param string|null $exceptionMessage If an Exception should be thrown, the expected message */ #[DataProvider('dataCheck')] + #[TestDox('The importer checks for errors')] public function testCheck(?string $db, $from, ?string $exceptionMessage) { if ($exceptionMessage) { @@ -383,7 +373,7 @@ public function testCheck(?string $db, $from, ?string $exceptionMessage) $importer = new MysqliImporter(); if ($db) { - $importer->setDbo($this->createMock($db)); + $importer->setDbo($this->createStub($db)); } if ($from) { diff --git a/Tests/Mysqli/MysqliPreparedStatementTest.php b/Tests/Mysqli/MysqliPreparedStatementTest.php index 38d73d56..5d916df8 100644 --- a/Tests/Mysqli/MysqliPreparedStatementTest.php +++ b/Tests/Mysqli/MysqliPreparedStatementTest.php @@ -10,7 +10,11 @@ use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\Mysqli\MysqliStatement; use Joomla\Test\DatabaseTestCase; +use Joomla\Test\TestHelper; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +#[RequiresPhpExtension('mysqli')] class MysqliPreparedStatementTest extends DatabaseTestCase { /** @@ -22,7 +26,7 @@ public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); - if (!static::$connection || static::$connection->getName() !== 'mysqli') { + if (!static::$connection) { self::markTestSkipped('MySQL database not configured.'); } } @@ -88,17 +92,11 @@ public function testPrepareParameterKeyMappingWithDuplicateKey() $rawQuery ); - $refObject = new \ReflectionObject($mysqliStatementObject); - $refMapping = $refObject->getProperty('parameterKeyMapping'); - /** @noinspection PhpExpressionResultUnusedInspection */ - $refMapping->setAccessible(true); - $parameterKeyMapping = $refMapping->getValue($mysqliStatementObject); - $this->assertEquals( [ ':search' => [0, 1], ], - $parameterKeyMapping + TestHelper::getValue($mysqliStatementObject, 'parameterKeyMapping') ); } @@ -116,26 +114,19 @@ public function testPrepareParameterKeyMappingWithSingleKey() $rawQuery ); - $refObject = new \ReflectionObject($mysqliStatementObject); - $refMapping = $refObject->getProperty('parameterKeyMapping'); - /** @noinspection PhpExpressionResultUnusedInspection */ - $refMapping->setAccessible(true); - $parameterKeyMapping = $refMapping->getValue($mysqliStatementObject); - $this->assertEquals( [ ':search' => [0], ':search2' => [1], ], - $parameterKeyMapping + TestHelper::getValue($mysqliStatementObject, 'parameterKeyMapping') ); } /** * Make sure the mysqli driver correctly runs queries with named parameters appearing more than once. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testPreparedStatementWithDuplicateKey() { $statement = 'SELECT * FROM dbtest WHERE `title` LIKE :search OR `description` LIKE :search'; @@ -148,9 +139,8 @@ public function testPreparedStatementWithDuplicateKey() /** * Regression test to ensure running queries with named parameters appearing once didn't break. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testPreparedStatementWithSingleKey() { $statement = 'SELECT * FROM dbtest WHERE `title` LIKE :search OR `description` LIKE :search2'; diff --git a/Tests/Mysqli/MysqliQueryTest.php b/Tests/Mysqli/MysqliQueryTest.php index 6b5893fe..31cbb82d 100644 --- a/Tests/Mysqli/MysqliQueryTest.php +++ b/Tests/Mysqli/MysqliQueryTest.php @@ -9,7 +9,8 @@ use Joomla\Database\DatabaseInterface; use Joomla\Database\Mysqli\MysqliQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -27,7 +28,7 @@ class MysqliQueryTest extends TestCase /** * Mock database driver * - * @var MockObject|DatabaseInterface + * @var Stub|DatabaseInterface */ private $db; @@ -42,7 +43,7 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(DatabaseInterface::class); + $this->db = $this->createStub(DatabaseInterface::class); $this->query = new MysqliQuery($this->db); } @@ -60,17 +61,15 @@ public static function dataConcatenate(): array } /** - * @testdox A SQL statement for concatenating values is generated - * * @param string[] $values An array of values to concatenate. * @param string|null $separator As separator to place between each value. * @param string $expected The expected query string. */ #[DataProvider('dataConcatenate')] + #[TestDox('A SQL statement for concatenating values is generated')] public function testConcatenate(array $values, ?string $separator, string $expected) { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); @@ -81,9 +80,7 @@ public function testConcatenate(array $values, ?string $separator, string $expec ); } - /** - * @testdox A SQL statement for the MySQL find_in_set() function is generated - */ + #[TestDox('A SQL statement for the MySQL find_in_set() function is generated')] public function testFindInSet() { $this->assertSame( @@ -92,13 +89,10 @@ public function testFindInSet() ); } - /** - * @testdox A SQL statement to concatenate a group of values is generated - */ + #[TestDox('A SQL statement to concatenate a group of values is generated')] public function testGroupConcat() { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); @@ -109,9 +103,7 @@ public function testGroupConcat() ); } - /** - * @testdox A SQL statement to get a random floating point value is generated - */ + #[TestDox('A SQL statement to get a random floating point value is generated')] public function testRand() { $this->assertSame( @@ -120,9 +112,7 @@ public function testRand() ); } - /** - * @testdox A SQL statement to prepend a string with a regex operator is generated - */ + #[TestDox('A SQL statement to prepend a string with a regex operator is generated')] public function testRegexp() { $this->assertSame( @@ -131,17 +121,13 @@ public function testRegexp() ); } - /** - * @testdox A string is cast as a character string for the driver - */ + #[TestDox('A string is cast as a character string for the driver')] public function testCastAsWithChar() { $this->assertSame('123', $this->query->castAs('CHAR', '123')); } - /** - * @testdox The length param is added to the CAST statement when provided - */ + #[TestDox('The length param is added to the CAST statement when provided')] public function testCastAsWithCharAndLengthParam() { $this->assertSame( @@ -150,9 +136,7 @@ public function testCastAsWithCharAndLengthParam() ); } - /** - * @testdox Test castAs behaviour with INT (adds 0 to the input) - */ + #[TestDox('Test castAs behaviour with INT (adds 0 to the input)')] public function testCastAsWithIntegerType() { $this->assertSame( diff --git a/Tests/Mysqli/MysqliStatementTest.php b/Tests/Mysqli/MysqliStatementTest.php index 669b46f4..6f697498 100644 --- a/Tests/Mysqli/MysqliStatementTest.php +++ b/Tests/Mysqli/MysqliStatementTest.php @@ -10,10 +10,13 @@ use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\Mysqli\MysqliStatement; use Joomla\Test\DatabaseTestCase; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; /** * Test class for Joomla\Database\Mysqli\MysqliStatement */ +#[RequiresPhpExtension('mysqli')] class MysqliStatementTest extends DatabaseTestCase { /** @@ -25,7 +28,7 @@ public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); - if (!static::$connection || static::$connection->getName() !== 'mysqli') { + if (!static::$connection) { self::markTestSkipped('MySQL database not configured.'); } } @@ -70,9 +73,8 @@ protected function tearDown(): void /** * Regression test to ensure that named values with matching named params are correctly prepared, this simulates a whereIn condition. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testStatementPreparesManyArrayValues() { $query = 'SELECT * FROM dbtest WHERE id IN (:preparedArray1,:preparedArray2,:preparedArray3,:preparedArray4,:preparedArray5,:preparedArray6,:preparedArray7,:preparedArray8,:preparedArray9,:preparedArray10)'; @@ -82,9 +84,8 @@ public function testStatementPreparesManyArrayValues() /** * Regression test to ensure that named values with matching named params are correctly prepared (part 2), this simulates a general use case. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testStatementWithKeysMatching() { $query = 'SELECT * FROM dbtest WHERE `id` = :id AND `title` = :id_title'; @@ -95,9 +96,8 @@ public function testStatementWithKeysMatching() /** * Regression test to ensure that named values with matching named params are correctly prepared (part 3). * This simulates a general use case for a search function where we reuse the same prepared statement term. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testStatementWithMultipleUseOfVars() { $query = 'SELECT * FROM `dbtest` WHERE `description` LIKE :search_term AND `title` LIKE :search_term'; diff --git a/Tests/Pgsql/PgsqlDriverTest.php b/Tests/Pgsql/PgsqlDriverTest.php index ee297a71..e6cbe1fb 100644 --- a/Tests/Pgsql/PgsqlDriverTest.php +++ b/Tests/Pgsql/PgsqlDriverTest.php @@ -13,10 +13,13 @@ use Joomla\Database\Pgsql\PgsqlQuery; use Joomla\Database\Tests\AbstractDatabaseDriverTestCase; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\Attributes\TestDox; /** * Test class for Joomla\Database\Pgsql\PgsqlDriver */ +#[RequiresPhpExtension('pdo_pgsql')] class PgsqlDriverTest extends AbstractDatabaseDriverTestCase { /** @@ -31,7 +34,7 @@ public static function setUpBeforeClass(): void parent::setUpBeforeClass(); - if (!static::$connection || static::$connection->getName() !== 'pgsql') { + if (!static::$connection) { self::markTestSkipped('PostgreSQL database not configured.'); } } @@ -192,9 +195,7 @@ public static function dataQuoteName(): array * Overrides for parent class test cases */ - /** - * @testdox An object can be inserted into the database - */ + #[TestDox('An object can be inserted into the database')] public function testInsertObject() { $this->loadExampleData(); @@ -222,9 +223,7 @@ public function testInsertObject() $this->assertNotNull($data->id, 'When given a key, the insertObject method should set the row ID'); } - /** - * @testdox A database table can be renamed - */ + #[TestDox('A database table can be renamed')] public function testRenameTable() { $oldTableName = '#__dbtest'; @@ -299,9 +298,7 @@ public function testRenameTable() * Test cases for this subclass */ - /** - * @testdox The database collation can be retrieved - */ + #[TestDox('The database collation can be retrieved')] public function testGetCollation() { $this->assertNotFalse( @@ -309,9 +306,7 @@ public function testGetCollation() ); } - /** - * @testdox The database connection collation can be retrieved - */ + #[TestDox('The database connection collation can be retrieved')] public function testGetConnectionCollation() { $this->assertNotFalse( @@ -319,27 +314,16 @@ public function testGetConnectionCollation() ); } - /** - * @testdox The database connection encryption can be retrieved - */ + #[TestDox('The database connection encryption can be retrieved')] public function testGetConnectionEncryption() { - $expectedResult = ''; - - if (\getenv('TRAVIS') === 'true' && in_array(\getenv('PGSQL_VERSION'), ['9.5', '9.6', '10.0'])) { - $expectedResult = 'TLSv1.2 (ECDHE-RSA-AES256-GCM-SHA384)'; - } - - $this->assertSame( - $expectedResult, + $this->assertEmpty( static::$connection->getConnectionEncryption(), 'The database connection is not encrypted by default' ); } - /** - * @testdox A list of queries to create the given tables is returned - */ + #[TestDox('A list of queries to create the given tables is returned')] public function testGetTableCreate() { $this->assertEmpty( @@ -348,9 +332,7 @@ public function testGetTableCreate() ); } - /** - * @testdox Information about the keys of a database table is returned - */ + #[TestDox('Information about the keys of a database table is returned')] public function testGetTableKeys() { $this->assertEquals( @@ -367,9 +349,7 @@ public function testGetTableKeys() ); } - /** - * @testdox Information about the sequences of a database table is returned - */ + #[TestDox('Information about the sequences of a database table is returned')] public function testGetTableSequences() { $sequence = [ @@ -398,9 +378,7 @@ public function testGetTableSequences() ); } - /** - * @testdox The last value of a table sequence is returned - */ + #[TestDox('The last value of a table sequence is returned')] public function testGetSequenceLastValue() { $this->assertTrue( @@ -408,9 +386,7 @@ public function testGetSequenceLastValue() ); } - /** - * @testdox The last value of a table sequence is returned - */ + #[TestDox('The last value of a table sequence is returned')] public function testGetSequenceIsCalled() { $this->assertTrue( @@ -418,9 +394,7 @@ public function testGetSequenceIsCalled() ); } - /** - * @testdox A transaction can be started and committed - */ + #[TestDox('A transaction can be started and committed')] public function testTransactionCommit() { $this->loadExampleData(); @@ -475,12 +449,11 @@ public static function dataTransactionRollback(): array } /** - * @testdox A transaction can be started and committed - * * @param string|null $toSavepoint Savepoint name to rollback transaction to * @param integer $tupleCount Number of tuples found after insertion and rollback */ #[DataProvider('dataTransactionRollback')] + #[TestDox('A transaction can be started and committed')] public function testTransactionRollback(?string $toSavepoint, int $tupleCount) { $this->loadExampleData(); @@ -548,9 +521,7 @@ public function testTransactionRollback(?string $toSavepoint, int $tupleCount) $this->assertCount($tupleCount, $transactionRows); } - /** - * @testdox The database driver reports if it is supported in the present environment - */ + #[TestDox('The database driver reports if it is supported in the present environment')] public function testIsSupported() { $this->assertTrue( @@ -558,9 +529,7 @@ public function testIsSupported() ); } - /** - * @testdox Binary values are correctly supported - */ + #[TestDox('Binary values are correctly supported')] public function testQuoteAndDecodeBinary() { $this->loadExampleData(); @@ -647,9 +616,7 @@ public function testQuoteAndDecodeBinary() $this->assertEquals($expected, $result); } - /** - * @testdox The database connection can be retrieved - */ + #[TestDox('The database connection can be retrieved')] public function testGetConnection() { $this->assertInstanceOf( @@ -658,9 +625,7 @@ public function testGetConnection() ); } - /** - * @testdox The name of the database driver is retrieved - */ + #[TestDox('The name of the database driver is retrieved')] public function testGetName() { $this->assertSame( @@ -669,9 +634,7 @@ public function testGetName() ); } - /** - * @testdox The type of server for the database driver is retrieved - */ + #[TestDox('The type of server for the database driver is retrieved')] public function testGetServerType() { $this->assertSame( @@ -680,9 +643,7 @@ public function testGetServerType() ); } - /** - * @testdox The null date for the server type is retrieved - */ + #[TestDox('The null date for the server type is retrieved')] public function testGetNullDate() { $this->assertSame( @@ -691,9 +652,7 @@ public function testGetNullDate() ); } - /** - * @testdox An exporter for the database driver can be created - */ + #[TestDox('An exporter for the database driver can be created')] public function testGetExporter() { $this->assertInstanceOf( @@ -702,9 +661,7 @@ public function testGetExporter() ); } - /** - * @testdox An importer for the database driver can be created - */ + #[TestDox('An importer for the database driver can be created')] public function testGetImporter() { $this->assertInstanceOf( @@ -713,9 +670,7 @@ public function testGetImporter() ); } - /** - * @testdox A new query instance can be created - */ + #[TestDox('A new query instance can be created')] public function testGetQueryNewInstance() { $this->assertInstanceOf( diff --git a/Tests/Pgsql/PgsqlExporterTest.php b/Tests/Pgsql/PgsqlExporterTest.php index 468b7269..e2a7a946 100644 --- a/Tests/Pgsql/PgsqlExporterTest.php +++ b/Tests/Pgsql/PgsqlExporterTest.php @@ -11,7 +11,8 @@ use Joomla\Database\Pgsql\PgsqlExporter; use Joomla\Database\Pgsql\PgsqlQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -22,7 +23,7 @@ class PgsqlExporterTest extends TestCase /** * Mock database driver * - * @var MockObject|PgsqlDriver + * @var Stub|PgsqlDriver */ private $db; @@ -37,20 +38,17 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(PgsqlDriver::class); + $this->db = $this->createStub(PgsqlDriver::class); - $this->db->expects($this->any()) - ->method('getPrefix') + $this->db->method('getPrefix') ->willReturn('jos_'); - $this->db->expects($this->any()) - ->method('createQuery') + $this->db->method('createQuery') ->willReturnCallback(function () { return new PgsqlQuery($this->db); }); - $this->db->expects($this->any()) - ->method('getTableColumns') + $this->db->method('getTableColumns') ->willReturn( [ 'id' => (object) [ @@ -88,8 +86,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('getTableKeys') + $this->db->method('getTableKeys') ->willReturn( [ (object) [ @@ -102,8 +99,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('getTableSequences') + $this->db->method('getTableSequences') ->willReturn( [ (object) [ @@ -121,8 +117,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('quoteName') + $this->db->method('quoteName') ->willReturnCallback( function ($name, $as = null) { if (is_string($name)) { @@ -235,13 +230,12 @@ public static function dataCastingToString(): array } /** - * @testdox The exporter can be cast to a string - * * @param boolean $withStructure True to export the structure, false to not. * @param boolean $withData True to export the data, false to not. * @param string $expectedXml Expected XML string. */ #[DataProvider('dataCastingToString')] + #[TestDox('The exporter can be cast to a string')] public function testCastingToString(bool $withStructure, bool $withData, string $expectedXml) { $exporter = new PgsqlExporter(); @@ -252,8 +246,7 @@ public function testCastingToString(bool $withStructure, bool $withData, string ->withData($withData); if ($withData) { - $this->db->expects($this->once()) - ->method('loadObjectList') + $this->db->method('loadObjectList') ->willReturn( [ (object) [ @@ -306,13 +299,12 @@ public static function dataCheck(): array } /** - * @testdox The exporter checks for errors - * * @param string|null $db Database driver to set in the exporter. * @param string[]|string|null $from Database tables to export from. * @param string|null $exceptionMessage If an Exception should be thrown, the expected message */ #[DataProvider('dataCheck')] + #[TestDox('The exporter checks for errors')] public function testCheck(?string $db, $from, ?string $exceptionMessage) { if ($exceptionMessage) { @@ -323,7 +315,7 @@ public function testCheck(?string $db, $from, ?string $exceptionMessage) $exporter = new PgsqlExporter(); if ($db) { - $exporter->setDbo($this->createMock($db)); + $exporter->setDbo($this->createStub($db)); } if ($from) { diff --git a/Tests/Pgsql/PgsqlImporterTest.php b/Tests/Pgsql/PgsqlImporterTest.php index b25ba792..1aec52bf 100644 --- a/Tests/Pgsql/PgsqlImporterTest.php +++ b/Tests/Pgsql/PgsqlImporterTest.php @@ -11,7 +11,8 @@ use Joomla\Database\Pgsql\PgsqlImporter; use Joomla\Database\Pgsql\PgsqlQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -22,7 +23,7 @@ class PgsqlImporterTest extends TestCase /** * Mock database driver * - * @var MockObject|PgsqlDriver + * @var Stub|PgsqlDriver */ private $db; @@ -63,20 +64,17 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(PgsqlDriver::class); + $this->db = $this->createStub(PgsqlDriver::class); - $this->db->expects($this->any()) - ->method('getPrefix') + $this->db->method('getPrefix') ->willReturn('jos_'); - $this->db->expects($this->any()) - ->method('createQuery') + $this->db->method('createQuery') ->willReturnCallback(function () { return new PgsqlQuery($this->db); }); - $this->db->expects($this->any()) - ->method('getTableColumns') + $this->db->method('getTableColumns') ->willReturn( [ 'id' => (object) [ @@ -98,8 +96,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('getTableKeys') + $this->db->method('getTableKeys') ->willReturn( [ (object) [ @@ -112,16 +109,14 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('getTableList') + $this->db->method('getTableList') ->willReturn( [ 'jos_dbtest', ] ); - $this->db->expects($this->any()) - ->method('getTableSequences') + $this->db->method('getTableSequences') ->willReturn( [ (object) [ @@ -139,8 +134,7 @@ protected function setUp(): void ] ); - $this->db->expects($this->any()) - ->method('insertObject') + $this->db->method('insertObject') ->willReturnCallback( function ($table, &$object, $key = null) { if (!isset($this->executedInsertObjects[$table])) { @@ -153,8 +147,7 @@ function ($table, &$object, $key = null) { } ); - $this->db->expects($this->any()) - ->method('quoteName') + $this->db->method('quoteName') ->willReturnCallback( function ($name, $as = null) { if (is_string($name)) { @@ -171,8 +164,7 @@ function ($name, $as = null) { } ); - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback( function ($text, $escape = true) { if (is_string($text)) { @@ -189,8 +181,7 @@ function ($text, $escape = true) { } ); - $this->db->expects($this->any()) - ->method('setQuery') + $this->db->method('setQuery') ->willReturnCallback( function ($query, $offset = 0, $limit = 0) { $this->executedQueries[] = $query; @@ -205,7 +196,7 @@ function ($query, $offset = 0, $limit = 0) { */ protected function tearDown(): void { - $this->expectedInsertObjects = []; + $this->executedInsertObjects = []; $this->executedQueries = []; } @@ -318,8 +309,6 @@ public static function dataImport(): array } /** - * @testdox The importer processes a XML document - * * @param boolean $mergeStructure True to merge the structure. * @param boolean $importData True to import the data. * @param \SimpleXMLElement $from XML document to import. @@ -327,6 +316,7 @@ public static function dataImport(): array * @param string[] $expectedInsertObjects The expected objects to be given to the database's insertObject method. */ #[DataProvider('dataImport')] + #[TestDox('The importer processes a XML document')] public function testImport(bool $mergeStructure, bool $importData, \SimpleXMLElement $from, array $expectedQueries, array $expectedInsertObjects) { $importer = new PgsqlImporter(); @@ -380,13 +370,12 @@ public static function dataCheck(): array } /** - * @testdox The importer checks for errors - * * @param string|null $db Database driver to set in the importer. * @param string[]|string|null $from Database structure to import. * @param string|null $exceptionMessage If an Exception should be thrown, the expected message */ #[DataProvider('dataCheck')] + #[TestDox('The importer checks for errors')] public function testCheck(?string $db, $from, ?string $exceptionMessage) { if ($exceptionMessage) { @@ -397,7 +386,7 @@ public function testCheck(?string $db, $from, ?string $exceptionMessage) $importer = new PgsqlImporter(); if ($db) { - $importer->setDbo($this->createMock($db)); + $importer->setDbo($this->createStub($db)); } if ($from) { diff --git a/Tests/Pgsql/PgsqlPreparedStatementTest.php b/Tests/Pgsql/PgsqlPreparedStatementTest.php index 41b4fe18..a7533858 100644 --- a/Tests/Pgsql/PgsqlPreparedStatementTest.php +++ b/Tests/Pgsql/PgsqlPreparedStatementTest.php @@ -9,10 +9,13 @@ use Joomla\Database\DatabaseDriver; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Test\DatabaseTestCase; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; /** * Test class for Joomla\Database\Pgsql\PgsqlStatement */ +#[RequiresPhpExtension('pdo_pgsql')] class PgsqlPreparedStatementTest extends DatabaseTestCase { /** @@ -24,7 +27,7 @@ public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); - if (!static::$connection || static::$connection->getName() !== 'pgsql') { + if (!static::$connection) { self::markTestSkipped('PostgreSQL database not configured.'); } } @@ -69,9 +72,8 @@ protected function tearDown(): void /** * Make sure the mysqli driver correctly runs queries with named parameters appearing more than once. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testPreparedStatementWithDuplicateKey() { $dummyValue = 'test'; @@ -89,9 +91,8 @@ public function testPreparedStatementWithDuplicateKey() /** * Regression test to ensure running queries with named parameters appearing once didn't break. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testPreparedStatementWithSingleKey() { $dummyValue = 'test'; diff --git a/Tests/Pgsql/PgsqlQueryTest.php b/Tests/Pgsql/PgsqlQueryTest.php index b04f63a6..7ec5d2d7 100644 --- a/Tests/Pgsql/PgsqlQueryTest.php +++ b/Tests/Pgsql/PgsqlQueryTest.php @@ -9,7 +9,8 @@ use Joomla\Database\DatabaseInterface; use Joomla\Database\Pgsql\PgsqlQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -27,7 +28,7 @@ class PgsqlQueryTest extends TestCase /** * Mock database driver * - * @var MockObject|DatabaseInterface + * @var Stub|DatabaseInterface */ private $db; @@ -42,21 +43,17 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(DatabaseInterface::class); + $this->db = $this->createStub(DatabaseInterface::class); $this->query = new PgsqlQuery($this->db); } - /** - * @testdox A string is cast as a character string for the driver - */ + #[TestDox('A string is cast as a character string for the driver')] public function testCastAsWithChar() { $this->assertSame('foo::text', $this->query->castAs('CHAR', 'foo')); } - /** - * @testdox The length param is added to the CAST statement when provided - */ + #[TestDox('The length param is added to the CAST statement when provided')] public function testCastAsWithCharAndLengthParam() { $this->assertSame( @@ -65,9 +62,7 @@ public function testCastAsWithCharAndLengthParam() ); } - /** - * @testdox Test castAs behaviour with INT - */ + #[TestDox('Test castAs behaviour with INT')] public function testCastAsWithIntegerType() { $this->assertSame( @@ -90,17 +85,15 @@ public static function dataConcatenate(): array } /** - * @testdox A SQL statement for concatenating values is generated - * * @param string[] $values An array of values to concatenate. * @param string|null $separator As separator to place between each value. * @param string $expected The expected query string. */ #[DataProvider('dataConcatenate')] + #[TestDox('A SQL statement for concatenating values is generated')] public function testConcatenate(array $values, ?string $separator, string $expected) { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); @@ -111,9 +104,7 @@ public function testConcatenate(array $values, ?string $separator, string $expec ); } - /** - * @testdox A SQL statement for the current timestamp is generated - */ + #[TestDox('A SQL statement for the current timestamp is generated')] public function testCurrentTimestamp() { $this->assertSame( @@ -122,9 +113,7 @@ public function testCurrentTimestamp() ); } - /** - * @testdox A SQL statement for the MySQL find_in_set() function is generated - */ + #[TestDox('A SQL statement for the MySQL find_in_set() function is generated')] public function testFindInSet() { $this->assertSame( @@ -133,13 +122,10 @@ public function testFindInSet() ); } - /** - * @testdox A SQL statement to concatenate a group of values is generated - */ + #[TestDox('A SQL statement to concatenate a group of values is generated')] public function testGroupConcat() { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); @@ -150,9 +136,7 @@ public function testGroupConcat() ); } - /** - * @testdox A SQL statement to extract the year from a date is generated - */ + #[TestDox('A SQL statement to extract the year from a date is generated')] public function testYear() { $this->assertSame( @@ -161,9 +145,7 @@ public function testYear() ); } - /** - * @testdox A SQL statement to extract the month from a date is generated - */ + #[TestDox('A SQL statement to extract the month from a date is generated')] public function testMonth() { $this->assertSame( @@ -172,9 +154,7 @@ public function testMonth() ); } - /** - * @testdox A SQL statement to extract the day from a date is generated - */ + #[TestDox('A SQL statement to extract the day from a date is generated')] public function testDay() { $this->assertSame( @@ -183,9 +163,7 @@ public function testDay() ); } - /** - * @testdox A SQL statement to extract the hour from a date is generated - */ + #[TestDox('A SQL statement to extract the hour from a date is generated')] public function testHour() { $this->assertSame( @@ -194,9 +172,7 @@ public function testHour() ); } - /** - * @testdox A SQL statement to extract the minute from a date is generated - */ + #[TestDox('A SQL statement to extract the minute from a date is generated')] public function testMinute() { $this->assertSame( @@ -205,9 +181,7 @@ public function testMinute() ); } - /** - * @testdox A SQL statement to extract the second from a date is generated - */ + #[TestDox('A SQL statement to extract the second from a date is generated')] public function testSecond() { $this->assertSame( @@ -230,14 +204,13 @@ public static function dataDateAdd(): array } /** - * @testdox A SQL statement for adding date values is generated - * * @param string $date The db quoted string representation of the date to add to. May be date or datetime * @param string $interval The string representation of the appropriate number of units * @param string $datePart The part of the date to perform the addition on * @param string $expected The expected query string. */ #[DataProvider('dataDateAdd')] + #[TestDox('A SQL statement for adding date values is generated')] public function testDateAdd(string $date, string $interval, string $datePart, string $expected) { $this->assertSame( @@ -246,9 +219,7 @@ public function testDateAdd(string $date, string $interval, string $datePart, st ); } - /** - * @testdox A SQL statement to get a random floating point value is generated - */ + #[TestDox('A SQL statement to get a random floating point value is generated')] public function testRand() { $this->assertSame( @@ -257,9 +228,7 @@ public function testRand() ); } - /** - * @testdox A SQL statement to prepend a string with a regex operator is generated - */ + #[TestDox('A SQL statement to prepend a string with a regex operator is generated')] public function testRegexp() { $this->assertSame( diff --git a/Tests/Query/QueryElementTest.php b/Tests/Query/QueryElementTest.php index 7fa6eccf..66028284 100644 --- a/Tests/Query/QueryElementTest.php +++ b/Tests/Query/QueryElementTest.php @@ -8,6 +8,7 @@ use Joomla\Database\Query\QueryElement; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; /** @@ -59,12 +60,11 @@ public static function dataInstantiation(): array } /** - * @testdox The object is correctly configured when instantiated - * * @param array $element values for base element * @param array $expected values for expected fields */ #[DataProvider('dataInstantiation')] + #[TestDox('The object is correctly configured when instantiated')] public function testInstantiation(array $element, array $expected) { $baseElement = new QueryElement($element['name'], $element['elements'], $element['glue']); @@ -130,14 +130,13 @@ public static function dataCastingToString(): array } /** - * @testdox A query element is converted to a string - * * @param string $name The name of the element. * @param mixed $elements String or array. * @param string $glue The glue for elements. * @param string $expected The expected value. */ #[DataProvider('dataCastingToString')] + #[TestDox('A query element is converted to a string')] public function testCastingToString($name, $elements, $glue, $expected) { $this->assertThat( @@ -204,14 +203,13 @@ public static function dataAppend(): array } /** - * @testdox Data can be appended to a query element - * * @param array $element base element values * @param array $append append element values * @param array $expected expected element values for elements field after append * @param string $string expected value of toString (not used in this test) */ #[DataProvider('dataAppend')] + #[TestDox('Data can be appended to a query element')] public function testAppend($element, $append, $expected, $string) { $baseElement = new QueryElement($element['name'], $element['elements'], $element['glue']); @@ -226,9 +224,7 @@ public function testAppend($element, $append, $expected, $string) ); } - /** - * @testdox A query element can be cloned with a custom array property - */ + #[TestDox('A query element can be cloned with a custom array property')] public function testCloneWithCustomArrayProperty() { $baseElement = new QueryElement(null, null); @@ -242,9 +238,7 @@ public function testCloneWithCustomArrayProperty() $this->assertCount(0, $cloneElement->testArray); } - /** - * @testdox A query element can be cloned with a custom object property - */ + #[TestDox('A query element can be cloned with a custom object property')] public function testCloneWithCustomObjectProperty() { $baseElement = new QueryElement(null, null); diff --git a/Tests/Service/DatabaseProviderTest.php b/Tests/Service/DatabaseProviderTest.php index 6a1b31f7..10495b86 100644 --- a/Tests/Service/DatabaseProviderTest.php +++ b/Tests/Service/DatabaseProviderTest.php @@ -13,6 +13,7 @@ use Joomla\Database\Service\DatabaseProvider; use Joomla\DI\Container; use Joomla\Registry\Registry; +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; /** @@ -46,9 +47,7 @@ protected function setUp(): void $this->container->set('config', $config); } - /** - * @testdox Verify that the DatabaseProvider returns a DatabaseInterface object - */ + #[TestDox('Verify that the DatabaseProvider returns a DatabaseInterface object')] public function testVerifyTheDatabaseDriverIsRegisteredToTheContainer() { $this->container->registerServiceProvider(new DatabaseProvider()); @@ -59,9 +58,7 @@ public function testVerifyTheDatabaseDriverIsRegisteredToTheContainer() ); } - /** - * @testdox Verify that the DatabaseProvider returns a DatabaseFactory object - */ + #[TestDox('Verify that the DatabaseProvider returns a DatabaseFactory object')] public function testVerifyTheDatabaseFactoryIsRegisteredToTheContainer() { $this->container->registerServiceProvider(new DatabaseProvider()); diff --git a/Tests/Sqlite/SqliteDriverTest.php b/Tests/Sqlite/SqliteDriverTest.php index 3d1ec2fc..927156e0 100644 --- a/Tests/Sqlite/SqliteDriverTest.php +++ b/Tests/Sqlite/SqliteDriverTest.php @@ -14,10 +14,14 @@ use Joomla\Database\Sqlite\SqliteQuery; use Joomla\Database\Tests\AbstractDatabaseDriverTestCase; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\Attributes\TestDox; /** * Test class for Joomla\Database\Sqlite\SqliteDriver */ +#[RequiresPhpExtension('pdo_sqlite')] +#[RequiresPhpExtension('sqlite3')] class SqliteDriverTest extends AbstractDatabaseDriverTestCase { /** @@ -211,9 +215,7 @@ public static function dataQuoteName(): array * Overrides for parent class test cases */ - /** - * @testdox The list of tables is returned - */ + #[TestDox('The list of tables is returned')] public function testGetTableList() { $this->assertSame( @@ -225,9 +227,7 @@ public function testGetTableList() ); } - /** - * @testdox The minimum supported database version is retrieved - */ + #[TestDox('The minimum supported database version is retrieved')] public function testGetMinimum() { $this->assertNull( @@ -236,9 +236,7 @@ public function testGetMinimum() ); } - /** - * @testdox The number of rows returned by the query can be retrieved - */ + #[TestDox('The number of rows returned by the query can be retrieved')] public function testGetNumRows() { $this->loadExampleData(); @@ -259,9 +257,7 @@ public function testGetNumRows() * Test cases for this subclass */ - /** - * @testdox The database character set can be changed - */ + #[TestDox('The database character set can be changed')] public function testAlterDbCharacterSet() { $this->assertFalse( @@ -270,9 +266,7 @@ public function testAlterDbCharacterSet() ); } - /** - * @testdox A database can be created - */ + #[TestDox('A database can be created')] public function testCreateDatabase() { $this->assertTrue( @@ -281,9 +275,7 @@ public function testCreateDatabase() ); } - /** - * @testdox The database collation can be retrieved - */ + #[TestDox('The database collation can be retrieved')] public function testGetCollation() { $this->assertFalse( @@ -292,9 +284,7 @@ public function testGetCollation() ); } - /** - * @testdox The database connection collation can be retrieved - */ + #[TestDox('The database connection collation can be retrieved')] public function testGetConnectionCollation() { $this->assertFalse( @@ -303,9 +293,7 @@ public function testGetConnectionCollation() ); } - /** - * @testdox The database connection encryption can be retrieved - */ + #[TestDox('The database connection encryption can be retrieved')] public function testGetConnectionEncryption() { $this->assertEmpty( @@ -314,9 +302,7 @@ public function testGetConnectionEncryption() ); } - /** - * @testdox A list of queries to create the given tables is returned - */ + #[TestDox('A list of queries to create the given tables is returned')] public function testGetTableCreate() { $this->assertSame( @@ -326,9 +312,7 @@ public function testGetTableCreate() ); } - /** - * @testdox Information about the keys of a database table is returned - */ + #[TestDox('Information about the keys of a database table is returned')] public function testGetTableKeys() { $this->assertEquals( @@ -346,9 +330,7 @@ public function testGetTableKeys() ); } - /** - * @testdox The connection can be set to use UTF-8 encoding - */ + #[TestDox('The connection can be set to use UTF-8 encoding')] public function testSetUtf() { $this->assertFalse( @@ -356,9 +338,7 @@ public function testSetUtf() ); } - /** - * @testdox A database table can be truncated - */ + #[TestDox('A database table can be truncated')] public function testTruncateTable() { $this->loadExampleData(); @@ -368,9 +348,7 @@ public function testTruncateTable() $this->assertSame(4, static::$connection->getAffectedRows()); } - /** - * @testdox The database driver reports if it is supported in the present environment - */ + #[TestDox('The database driver reports if it is supported in the present environment')] public function testIsSupported() { $this->assertTrue( @@ -378,9 +356,7 @@ public function testIsSupported() ); } - /** - * @testdox A transaction can be started and committed - */ + #[TestDox('A transaction can be started and committed')] public function testTransactionCommit() { $this->loadExampleData(); @@ -435,12 +411,11 @@ public static function dataTransactionRollback() } /** - * @testdox A transaction can be started and committed - * * @param string|null $toSavepoint Savepoint name to rollback transaction to * @param integer $tupleCount Number of tuples found after insertion and rollback */ #[DataProvider('dataTransactionRollback')] + #[TestDox('A transaction can be started and committed')] public function testTransactionRollback(?string $toSavepoint, int $tupleCount) { $this->loadExampleData(); @@ -508,9 +483,7 @@ public function testTransactionRollback(?string $toSavepoint, int $tupleCount) $this->assertCount($tupleCount, $transactionRows); } - /** - * @testdox The database connection can be retrieved - */ + #[TestDox('The database connection can be retrieved')] public function testGetConnection() { $this->assertInstanceOf( @@ -519,9 +492,7 @@ public function testGetConnection() ); } - /** - * @testdox The name of the database driver is retrieved - */ + #[TestDox('The name of the database driver is retrieved')] public function testGetName() { $this->assertSame( @@ -530,9 +501,7 @@ public function testGetName() ); } - /** - * @testdox The type of server for the database driver is retrieved - */ + #[TestDox('The type of server for the database driver is retrieved')] public function testGetServerType() { $this->assertSame( @@ -541,9 +510,7 @@ public function testGetServerType() ); } - /** - * @testdox The null date for the server type is retrieved - */ + #[TestDox('The null date for the server type is retrieved')] public function testGetNullDate() { $this->assertSame( @@ -552,9 +519,7 @@ public function testGetNullDate() ); } - /** - * @testdox An exporter for the database driver can be created - */ + #[TestDox('An exporter for the database driver can be created')] public function testGetExporter() { $this->expectException(UnsupportedAdapterException::class); @@ -562,9 +527,7 @@ public function testGetExporter() static::$connection->getExporter(); } - /** - * @testdox An importer for the database driver can be created - */ + #[TestDox('An importer for the database driver can be created')] public function testGetImporter() { $this->expectException(UnsupportedAdapterException::class); @@ -572,9 +535,7 @@ public function testGetImporter() static::$connection->getImporter(); } - /** - * @testdox A new query instance can be created - */ + #[TestDox('A new query instance can be created')] public function testGetQueryNewInstance() { $this->assertInstanceOf( @@ -583,9 +544,7 @@ public function testGetQueryNewInstance() ); } - /** - * @testdox Binary values are correctly supported - */ + #[TestDox('Binary values are correctly supported')] public function testQuoteAndDecodeBinary() { $this->loadExampleData(); diff --git a/Tests/Sqlite/SqlitePreparedStatementTest.php b/Tests/Sqlite/SqlitePreparedStatementTest.php index 3ddb258c..ebaf8fa4 100644 --- a/Tests/Sqlite/SqlitePreparedStatementTest.php +++ b/Tests/Sqlite/SqlitePreparedStatementTest.php @@ -9,7 +9,11 @@ use Joomla\Database\DatabaseDriver; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Test\DatabaseTestCase; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +#[RequiresPhpExtension('pdo_sqlite')] +#[RequiresPhpExtension('sqlite3')] class SqlitePreparedStatementTest extends DatabaseTestCase { /** @@ -76,9 +80,8 @@ function (string $table): bool { /** * Make sure the mysqli driver correctly runs queries with named parameters appearing more than once. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testPreparedStatementWithDuplicateKey() { $dummyValue = 'test'; @@ -96,9 +99,8 @@ public function testPreparedStatementWithDuplicateKey() /** * Regression test to ensure running queries with named parameters appearing once didn't break. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testPreparedStatementWithSingleKey() { $dummyValue = 'test'; diff --git a/Tests/Sqlite/SqliteQueryTest.php b/Tests/Sqlite/SqliteQueryTest.php index 5a444d40..a408809d 100644 --- a/Tests/Sqlite/SqliteQueryTest.php +++ b/Tests/Sqlite/SqliteQueryTest.php @@ -9,7 +9,8 @@ use Joomla\Database\DatabaseInterface; use Joomla\Database\Sqlite\SqliteQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -27,7 +28,7 @@ class SqliteQueryTest extends TestCase /** * Mock database driver * - * @var MockObject|DatabaseInterface + * @var Stub|DatabaseInterface */ private $db; @@ -42,7 +43,7 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(DatabaseInterface::class); + $this->db = $this->createStub(DatabaseInterface::class); $this->query = new SqliteQuery($this->db); } @@ -60,14 +61,13 @@ public static function dataCharLength(): array } /** - * @testdox A SQL statement for checking the character length of a field is generated - * * @param string $field A value. * @param string|null $operator Comparison operator between charLength integer value and $condition * @param string|null $condition Integer value to compare charLength with. * @param string $expected The expected query string. */ #[DataProvider('dataCharLength')] + #[TestDox('A SQL statement for checking the character length of a field is generated')] public function testCharLength(string $field, ?string $operator, ?string $condition, string $expected) { $this->assertSame( @@ -90,17 +90,15 @@ public static function dataConcatenate(): array } /** - * @testdox A SQL statement for concatenating values is generated - * * @param string[] $values An array of values to concatenate. * @param string|null $separator As separator to place between each value. * @param string $expected The expected query string. */ #[DataProvider('dataConcatenate')] + #[TestDox('A SQL statement for concatenating values is generated')] public function testConcatenate(array $values, ?string $separator, string $expected) { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); @@ -111,13 +109,10 @@ public function testConcatenate(array $values, ?string $separator, string $expec ); } - /** - * @testdox A SQL statement to concatenate a group of values is generated - */ + #[TestDox('A SQL statement to concatenate a group of values is generated')] public function testGroupConcat() { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); diff --git a/Tests/Sqlsrv/SqlsrvDriverTest.php b/Tests/Sqlsrv/SqlsrvDriverTest.php index 19bda8fc..e833b586 100644 --- a/Tests/Sqlsrv/SqlsrvDriverTest.php +++ b/Tests/Sqlsrv/SqlsrvDriverTest.php @@ -13,10 +13,13 @@ use Joomla\Database\Sqlsrv\SqlsrvQuery; use Joomla\Database\Tests\AbstractDatabaseDriverTestCase; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\Attributes\TestDox; /** * Test class for Joomla\Database\Sqlsrv\SqlsrvDriver. */ +#[RequiresPhpExtension('sqlsrv')] class SqlsrvDriverTest extends AbstractDatabaseDriverTestCase { /** @@ -31,7 +34,7 @@ public static function setUpBeforeClass(): void parent::setUpBeforeClass(); - if (!static::$connection || static::$connection->getName() !== 'sqlsrv') { + if (!static::$connection) { self::markTestSkipped('SQL Server database not configured.'); } } @@ -226,10 +229,9 @@ public static function dataQuoteName(): array */ /** - * @testdox The first row of a result set can be loaded as a PHP object - * * @note This test case is an override from the parent because SQL Server casts the key to integers and has millisecond precision */ + #[TestDox('The first row of a result set can be loaded as a PHP object')] public function testLoadObject() { $this->loadExampleData(); @@ -252,10 +254,9 @@ public function testLoadObject() } /** - * @testdox All rows of a result set can be loaded as PHP objects - * * @note This test case is an override from the parent because SQL Server casts the key to integers and has millisecond precision */ + #[TestDox('All rows of a result set can be loaded as PHP objects')] public function testLoadObjectList() { $this->loadExampleData(); @@ -301,10 +302,9 @@ public function testLoadObjectList() } /** - * @testdox The first row of a result set can be loaded as an array - * * @note This test case is an override from the parent because SQL Server casts the key to integers and has millisecond precision */ + #[TestDox('The first row of a result set can be loaded as an array')] public function testLoadRow() { $this->loadExampleData(); @@ -327,10 +327,9 @@ public function testLoadRow() } /** - * @testdox All rows of a result set can be loaded as an array - * * @note This test case is an override from the parent because SQL Server casts the key to integers and has millisecond precision */ + #[TestDox('All rows of a result set can be loaded as an array')] public function testLoadRowList() { $this->loadExampleData(); @@ -376,10 +375,9 @@ public function testLoadRowList() } /** - * @testdox Queries converted to the querySet type are correctly built and executed - * * @note This test case is an override from the parent because the result set has more rows */ + #[TestDox('Queries converted to the querySet type are correctly built and executed')] public function testSelectToQuerySetWithUnionAll() { $this->loadExampleData(); @@ -418,9 +416,7 @@ public function testSelectToQuerySetWithUnionAll() * Test cases for this subclass */ - /** - * @testdox The database driver reports if it is supported in the present environment - */ + #[TestDox('The database driver reports if it is supported in the present environment')] public function testIsSupported() { $this->assertTrue( @@ -428,9 +424,7 @@ public function testIsSupported() ); } - /** - * @testdox The database collation can be retrieved - */ + #[TestDox('The database collation can be retrieved')] public function testGetCollation() { $this->assertSame( @@ -439,9 +433,7 @@ public function testGetCollation() ); } - /** - * @testdox The database connection collation can be retrieved - */ + #[TestDox('The database connection collation can be retrieved')] public function testGetConnectionCollation() { $this->assertSame( @@ -450,9 +442,7 @@ public function testGetConnectionCollation() ); } - /** - * @testdox The database connection encryption can be retrieved - */ + #[TestDox('The database connection encryption can be retrieved')] public function testGetConnectionEncryption() { $this->assertEmpty( @@ -461,9 +451,7 @@ public function testGetConnectionEncryption() ); } - /** - * @testdox A list of queries to create the given tables is returned - */ + #[TestDox('A list of queries to create the given tables is returned')] public function testGetTableCreate() { $this->assertEmpty( @@ -473,13 +461,12 @@ public function testGetTableCreate() } /** - * @testdox Information about the columns of a database table is returned - * * @param string $table The name of the database table. * @param boolean $typeOnly True (default) to only return field types. * @param array $expected Expected result. */ #[DataProvider('dataGetTableColumns')] + #[TestDox('Information about the columns of a database table is returned')] public function testGetTableColumns(string $table, bool $typeOnly, array $expected) { $this->assertEquals( @@ -488,9 +475,7 @@ public function testGetTableColumns(string $table, bool $typeOnly, array $expect ); } - /** - * @testdox Information about the keys of a database table is returned - */ + #[TestDox('Information about the keys of a database table is returned')] public function testGetTableKeys() { $this->assertEmpty( @@ -499,9 +484,7 @@ public function testGetTableKeys() ); } - /** - * @testdox The connection can be set to use UTF-8 encoding - */ + #[TestDox('The connection can be set to use UTF-8 encoding')] public function testSetUtf() { $this->assertTrue( @@ -509,9 +492,7 @@ public function testSetUtf() ); } - /** - * @testdox The database connection can be retrieved - */ + #[TestDox('The database connection can be retrieved')] public function testGetConnection() { $this->assertTrue( @@ -519,9 +500,7 @@ public function testGetConnection() ); } - /** - * @testdox The name of the database driver is retrieved - */ + #[TestDox('The name of the database driver is retrieved')] public function testGetName() { $this->assertSame( @@ -530,9 +509,7 @@ public function testGetName() ); } - /** - * @testdox The null date for the server type is retrieved - */ + #[TestDox('The null date for the server type is retrieved')] public function testGetNullDate() { $this->assertSame( @@ -541,9 +518,7 @@ public function testGetNullDate() ); } - /** - * @testdox An exporter for the database driver can be created - */ + #[TestDox('An exporter for the database driver can be created')] public function testGetExporter() { $this->expectException(UnsupportedAdapterException::class); @@ -551,9 +526,7 @@ public function testGetExporter() static::$connection->getExporter(); } - /** - * @testdox An importer for the database driver can be created - */ + #[TestDox('An importer for the database driver can be created')] public function testGetImporter() { $this->expectException(UnsupportedAdapterException::class); @@ -561,9 +534,7 @@ public function testGetImporter() static::$connection->getImporter(); } - /** - * @testdox A new query instance can be created - */ + #[TestDox('A new query instance can be created')] public function testGetQueryNewInstance() { $this->assertInstanceOf( diff --git a/Tests/Sqlsrv/SqlsrvPreparedStatementTest.php b/Tests/Sqlsrv/SqlsrvPreparedStatementTest.php index f21e4b1f..331086ac 100644 --- a/Tests/Sqlsrv/SqlsrvPreparedStatementTest.php +++ b/Tests/Sqlsrv/SqlsrvPreparedStatementTest.php @@ -10,10 +10,14 @@ use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\Sqlsrv\SqlsrvStatement; use Joomla\Test\DatabaseTestCase; +use Joomla\Test\TestHelper; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; /** * Test class for Joomla\Database\Sqlsrv\SqlsrvStatement */ +#[RequiresPhpExtension('sqlsrv')] class SqlsrvPreparedStatementTest extends DatabaseTestCase { /** @@ -25,7 +29,7 @@ public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); - if (!static::$connection || static::$connection->getName() !== 'sqlsrv') { + if (!static::$connection) { self::markTestSkipped('SQL Server database not configured.'); } } @@ -82,17 +86,11 @@ public function testPrepareParameterKeyMappingWithDuplicateKey() $rawQuery ); - $refObject = new \ReflectionObject($sqlsrvStatement); - $refMapping = $refObject->getProperty('parameterKeyMapping'); - /** @noinspection PhpExpressionResultUnusedInspection */ - $refMapping->setAccessible(true); - $parameterKeyMapping = $refMapping->getValue($sqlsrvStatement); - $this->assertEquals( [ ':search' => [0, 1], ], - $parameterKeyMapping + TestHelper::getValue($sqlsrvStatement, 'parameterKeyMapping') ); } @@ -110,26 +108,19 @@ public function testPrepareParameterKeyMappingWithSingleKey() $rawQuery ); - $refObject = new \ReflectionObject($sqlsrvStatement); - $refMapping = $refObject->getProperty('parameterKeyMapping'); - /** @noinspection PhpExpressionResultUnusedInspection */ - $refMapping->setAccessible(true); - $parameterKeyMapping = $refMapping->getValue($sqlsrvStatement); - $this->assertEquals( [ ':search' => [0], ':search2' => [1], ], - $parameterKeyMapping + TestHelper::getValue($sqlsrvStatement, 'parameterKeyMapping') ); } /** * Make sure the mysqli driver correctly runs queries with named parameters appearing more than once. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testPreparedStatementWithDuplicateKey() { $dummyValue = 'test'; @@ -147,9 +138,8 @@ public function testPreparedStatementWithDuplicateKey() /** * Regression test to ensure running queries with named parameters appearing once didn't break. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testPreparedStatementWithSingleKey() { $dummyValue = 'test'; diff --git a/Tests/Sqlsrv/SqlsrvQueryTest.php b/Tests/Sqlsrv/SqlsrvQueryTest.php index cddd4283..35d50991 100644 --- a/Tests/Sqlsrv/SqlsrvQueryTest.php +++ b/Tests/Sqlsrv/SqlsrvQueryTest.php @@ -9,7 +9,8 @@ use Joomla\Database\DatabaseInterface; use Joomla\Database\Sqlsrv\SqlsrvQuery; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; /** @@ -27,7 +28,7 @@ class SqlsrvQueryTest extends TestCase /** * Mock database driver * - * @var MockObject|DatabaseInterface + * @var Stub|DatabaseInterface */ private $db; @@ -42,21 +43,17 @@ protected function setUp(): void { parent::setUp(); - $this->db = $this->createMock(DatabaseInterface::class); + $this->db = $this->createStub(DatabaseInterface::class); $this->query = new SqlsrvQuery($this->db); } - /** - * @testdox A string is cast as a character string for the driver - */ + #[TestDox('A string is cast as a character string for the driver')] public function testCastAsWithChar() { $this->assertSame('CAST(foo as NVARCHAR(10))', $this->query->castAs('CHAR', 'foo')); } - /** - * @testdox The length param is added to the CAST statement when provided - */ + #[TestDox('The length param is added to the CAST statement when provided')] public function testCastAsWithCharAndLengthParam() { $this->assertSame( @@ -65,9 +62,7 @@ public function testCastAsWithCharAndLengthParam() ); } - /** - * @testdox Test castAs behaviour with INT - */ + #[TestDox('Test castAs behaviour with INT')] public function testCastAsWithIntegerType() { $this->assertSame( @@ -90,14 +85,13 @@ public static function dataCharLength(): array } /** - * @testdox A SQL statement for checking the character length of a field is generated - * * @param string $field A value. * @param string|null $operator Comparison operator between charLength integer value and $condition * @param string|null $condition Integer value to compare charLength with. * @param string $expected The expected query string. */ #[DataProvider('dataCharLength')] + #[TestDox('A SQL statement for checking the character length of a field is generated')] public function testCharLength(string $field, ?string $operator, ?string $condition, string $expected) { $this->assertSame( @@ -120,17 +114,15 @@ public static function dataConcatenate(): array } /** - * @testdox A SQL statement for concatenating values is generated - * * @param string[] $values An array of values to concatenate. * @param string|null $separator As separator to place between each value. * @param string $expected The expected query string. */ #[DataProvider('dataConcatenate')] + #[TestDox('A SQL statement for concatenating values is generated')] public function testConcatenate(array $values, ?string $separator, string $expected) { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); @@ -141,9 +133,7 @@ public function testConcatenate(array $values, ?string $separator, string $expec ); } - /** - * @testdox A SQL statement for the current timestamp is generated - */ + #[TestDox('A SQL statement for the current timestamp is generated')] public function testCurrentTimestamp() { $this->assertSame( @@ -152,9 +142,7 @@ public function testCurrentTimestamp() ); } - /** - * @testdox A SQL statement to get the length of a field is generated - */ + #[TestDox('A SQL statement to get the length of a field is generated')] public function testLength() { $this->assertSame( @@ -163,9 +151,7 @@ public function testLength() ); } - /** - * @testdox A SQL statement for the MySQL find_in_set() function is generated - */ + #[TestDox('A SQL statement for the MySQL find_in_set() function is generated')] public function testFindInSet() { $this->assertSame( @@ -174,13 +160,10 @@ public function testFindInSet() ); } - /** - * @testdox A SQL statement to concatenate a group of values is generated - */ + #[TestDox('A SQL statement to concatenate a group of values is generated')] public function testGroupConcat() { - $this->db->expects($this->any()) - ->method('quote') + $this->db->method('quote') ->willReturnCallback(function ($text, $escape = true) { return "'" . $text . "'"; }); @@ -191,9 +174,7 @@ public function testGroupConcat() ); } - /** - * @testdox A SQL statement to get a random floating point value is generated - */ + #[TestDox('A SQL statement to get a random floating point value is generated')] public function testRand() { $this->assertSame( diff --git a/Tests/Sqlsrv/SqlsrvStatementTest.php b/Tests/Sqlsrv/SqlsrvStatementTest.php index 07b449f1..c8cf1088 100644 --- a/Tests/Sqlsrv/SqlsrvStatementTest.php +++ b/Tests/Sqlsrv/SqlsrvStatementTest.php @@ -10,10 +10,13 @@ use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\Sqlsrv\SqlsrvStatement; use Joomla\Test\DatabaseTestCase; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; /** * Test class for Joomla\Database\Sqlsrv\SqlsrvStatement */ +#[RequiresPhpExtension('sqlsrv')] class SqlsrvStatementTest extends DatabaseTestCase { /** @@ -25,7 +28,7 @@ public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); - if (!static::$connection || static::$connection->getName() !== 'sqlsrv') { + if (!static::$connection) { self::markTestSkipped('SQL Server database not configured.'); } } @@ -70,9 +73,8 @@ protected function tearDown(): void /** * Regression test to ensure that named values with matching named params are correctly prepared, this simulates a whereIn condition. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testStatementPreparesManyArrayValues() { $query = 'SELECT * FROM dbtest WHERE id IN (:preparedArray1,:preparedArray2,:preparedArray3,:preparedArray4,:preparedArray5,:preparedArray6,:preparedArray7,:preparedArray8,:preparedArray9,:preparedArray10)'; @@ -82,9 +84,8 @@ public function testStatementPreparesManyArrayValues() /** * Regression test to ensure that named values with matching named params are correctly prepared (part 2), this simulates a general use case. - * - * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testStatementWithKeysMatching() { $query = 'SELECT * FROM dbtest WHERE id = :id AND title = :id_title'; @@ -93,11 +94,10 @@ public function testStatementWithKeysMatching() } /** - * Regression test to ensure that named values with matching named params are correctly prepared (part 3). - * This simulates a general use case for a search function where we reuse the same prepared statement term. - * -* @doesNotPerformAssertions - */ + * Regression test to ensure that named values with matching named params are correctly prepared (part 3). + * This simulates a general use case for a search function where we reuse the same prepared statement term. + */ + #[DoesNotPerformAssertions] public function testStatementWithMultipleUseOfVars() { $query = 'SELECT * FROM dbtest WHERE description LIKE :search_term AND title LIKE :search_term';