diff --git a/.doctrine-project.json b/.doctrine-project.json index d82aae12d..254bed621 100644 --- a/.doctrine-project.json +++ b/.doctrine-project.json @@ -99,4 +99,4 @@ "maintained": false } ] -} \ No newline at end of file +} diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml new file mode 100644 index 000000000..7df688992 --- /dev/null +++ b/.github/workflows/coding-standards.yml @@ -0,0 +1,39 @@ + +name: "Coding Standards" + +on: ["pull_request", "push"] + +jobs: + coding-standards: + name: "Coding Standards" + runs-on: "ubuntu-20.04" + + strategy: + matrix: + php-version: + - "7.4" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + tools: "cs2pr" + + - name: "Cache dependencies installed with Composer" + uses: "actions/cache@v2" + with: + path: "~/.composer/cache" + key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}" + restore-keys: "php-${{ matrix.php-version }}-composer-locked-" + + - name: "Install dependencies with Composer" + run: "composer install --no-interaction --no-progress --no-suggest" + + # https://github.com/doctrine/.github/issues/3 + - name: "Run PHP_CodeSniffer" + run: "vendor/bin/phpcs -q --no-colors --report=checkstyle | cs2pr" diff --git a/.gitignore b/.gitignore index e138de238..fc09e2fed 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ vendor composer.phar composer.lock phpunit.xml +/.phpunit.result.cache /phpcs.xml /.phpcs-cache diff --git a/.travis.yml b/.travis.yml index f72d67f9f..da7d831e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,12 +75,6 @@ jobs: install: - travis_retry composer update -n --prefer-dist - - stage: Code Quality - env: CODING_STANDARDS - php: 7.3 - script: - - ./vendor/bin/phpcs - - stage: Coverage php: 7.3 install: diff --git a/Command/CreateDatabaseDoctrineCommand.php b/Command/CreateDatabaseDoctrineCommand.php index 6afac11a6..e3eddb70a 100644 --- a/Command/CreateDatabaseDoctrineCommand.php +++ b/Command/CreateDatabaseDoctrineCommand.php @@ -57,6 +57,11 @@ protected function execute(InputInterface $input, OutputInterface $output) $params = $params['master']; } + // Since doctrine/dbal 2.11 master has been replaced by primary + if (isset($params['primary'])) { + $params = $params['primary']; + } + // Cannot inject `shard` option in parent::getDoctrineConnection // cause it will try to connect to a non-existing database if (isset($params['shards'])) { diff --git a/Command/DropDatabaseDoctrineCommand.php b/Command/DropDatabaseDoctrineCommand.php index fda4d1fd4..12368d4dc 100644 --- a/Command/DropDatabaseDoctrineCommand.php +++ b/Command/DropDatabaseDoctrineCommand.php @@ -66,6 +66,11 @@ protected function execute(InputInterface $input, OutputInterface $output) $params = $params['master']; } + // Since doctrine/dbal 2.11 master has been replaced by primary + if (isset($params['primary'])) { + $params = $params['primary']; + } + if (isset($params['shards'])) { $shards = $params['shards']; // Default select global @@ -74,7 +79,7 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($shards as $shard) { if ($shard['id'] === (int) $input->getOption('shard')) { // Select sharded database - $params = $shard; + $params = array_merge($params, $shard); unset($params['id']); break; } diff --git a/Command/Proxy/ImportDoctrineCommand.php b/Command/Proxy/ImportDoctrineCommand.php index 21722b144..b93224d52 100644 --- a/Command/Proxy/ImportDoctrineCommand.php +++ b/Command/Proxy/ImportDoctrineCommand.php @@ -31,7 +31,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - @trigger_error(sprintf('The "%s" (doctrine:database:import) command is deprecated, use a database client instead.', ImportDoctrineCommand::class), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s" (doctrine:database:import) command is deprecated, use a database client instead.', self::class), E_USER_DEPRECATED); DoctrineCommandHelper::setApplicationConnection($this->getApplication(), $input->getOption('connection')); diff --git a/Command/Proxy/RunSqlDoctrineCommand.php b/Command/Proxy/RunSqlDoctrineCommand.php index ff6c3b078..d784fcbdb 100644 --- a/Command/Proxy/RunSqlDoctrineCommand.php +++ b/Command/Proxy/RunSqlDoctrineCommand.php @@ -43,6 +43,10 @@ protected function execute(InputInterface $input, OutputInterface $output) { DoctrineCommandHelper::setApplicationConnection($this->getApplication(), $input->getOption('connection')); + // compatibility with doctrine/dbal 2.11+ + // where this option is also present and unsupported before we are not switching to use a ConnectionProvider + $input->setOption('connection', null); + return parent::execute($input, $output); } } diff --git a/ConnectionFactory.php b/ConnectionFactory.php index 2bebbcde4..6b40566dc 100644 --- a/ConnectionFactory.php +++ b/ConnectionFactory.php @@ -8,6 +8,7 @@ use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\AbstractMySQLDriver; use Doctrine\DBAL\DriverManager; +use Doctrine\DBAL\Exception; use Doctrine\DBAL\Exception\DriverException; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\Type; @@ -47,7 +48,10 @@ public function createConnection(array $params, Configuration $config = null, Ev $wrapperClass = null; if (isset($params['wrapperClass'])) { if (! is_subclass_of($params['wrapperClass'], Connection::class)) { - throw DBALException::invalidWrapperClass($params['wrapperClass']); + if (class_exists(DBALException::class)) { + throw DBALException::invalidWrapperClass($params['wrapperClass']); + } + throw Exception::invalidWrapperClass($params['wrapperClass']); } $wrapperClass = $params['wrapperClass']; @@ -97,13 +101,15 @@ public function createConnection(array $params, Configuration $config = null, Ev * For details have a look at DoctrineBundle issue #673. * * @throws DBALException + * @throws Exception */ private function getDatabasePlatform(Connection $connection) : AbstractPlatform { try { return $connection->getDatabasePlatform(); } catch (DriverException $driverException) { - throw new DBALException( + $exceptionClass = class_exists(DBALException::class)? DBALException::class : Exception::class; + throw new $exceptionClass( 'An exception occurred while establishing a connection to figure out your platform version.' . PHP_EOL . "You can circumvent this by setting a 'server_version' configuration value" . PHP_EOL . PHP_EOL . 'For further information have a look at:' . PHP_EOL . diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 482fa32fb..0d153f1e6 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -512,7 +512,7 @@ private function getOrmEntityManagersNode() : ArrayNodeDefinition ->append($this->getOrmCacheDriverNode('region_cache_driver')) ->scalarNode('region_lock_lifetime')->defaultValue(60)->end() ->booleanNode('log_enabled')->defaultValue($this->debug)->end() - ->scalarNode('region_lifetime')->defaultValue(0)->end() + ->scalarNode('region_lifetime')->defaultValue(3600)->end() ->booleanNode('enabled')->defaultValue(true)->end() ->scalarNode('factory')->end() ->end() diff --git a/DependencyInjection/DoctrineExtension.php b/DependencyInjection/DoctrineExtension.php index f0670706b..1c267114c 100644 --- a/DependencyInjection/DoctrineExtension.php +++ b/DependencyInjection/DoctrineExtension.php @@ -601,6 +601,8 @@ protected function loadOrmEntityManagerMappingInformation(array $entityManager, * entity_managers: * default: * second_level_cache: + * region_lifetime: 3600 + * region_lock_lifetime: 60 * region_cache_driver: apc * log_enabled: true * regions: @@ -633,7 +635,9 @@ protected function loadOrmSecondLevelCache(array $entityManager, Definition $orm $regionsId = sprintf('doctrine.orm.%s_second_level_cache.regions_configuration', $entityManager['name']); $driverId = $driverId ?: sprintf('doctrine.orm.%s_second_level_cache.region_cache_driver', $entityManager['name']); $configDef = $container->setDefinition($configId, new Definition('%doctrine.orm.second_level_cache.cache_configuration.class%')); - $regionsDef = $container->setDefinition($regionsId, new Definition('%doctrine.orm.second_level_cache.regions_configuration.class%')); + $regionsDef = $container + ->setDefinition($regionsId, new Definition('%doctrine.orm.second_level_cache.regions_configuration.class%')) + ->setArguments([$entityManager['second_level_cache']['region_lifetime'], $entityManager['second_level_cache']['region_lock_lifetime']]); $slcFactoryId = sprintf('doctrine.orm.%s_second_level_cache.default_cache_factory', $entityManager['name']); $factoryClass = isset($entityManager['second_level_cache']['factory']) ? $entityManager['second_level_cache']['factory'] : '%doctrine.orm.second_level_cache.default_cache_factory.class%'; diff --git a/Tests/Command/CreateDatabaseDoctrineTest.php b/Tests/Command/CreateDatabaseDoctrineTest.php index a90b36555..805661193 100644 --- a/Tests/Command/CreateDatabaseDoctrineTest.php +++ b/Tests/Command/CreateDatabaseDoctrineTest.php @@ -39,7 +39,10 @@ public function testExecute() : void array_merge(['command' => $command->getName()]) ); - $this->assertContains('Created database ' . sys_get_temp_dir() . '/' . $dbName . ' for connection named ' . $connectionName, $commandTester->getDisplay()); + $this->assertStringContainsString( + 'Created database ' . sys_get_temp_dir() . '/' . $dbName . ' for connection named ' . $connectionName, + $commandTester->getDisplay() + ); } /** @@ -81,12 +84,18 @@ public function testExecuteWithShardAlias(string $shardOption) : void $commandTester = new CommandTester($command); $commandTester->execute(['command' => $command->getName(), $shardOption => 1]); - $this->assertContains('Created database ' . sys_get_temp_dir() . '/shard_1 for connection named ' . $connectionName, $commandTester->getDisplay()); + $this->assertStringContainsString( + 'Created database ' . sys_get_temp_dir() . '/shard_1 for connection named ' . $connectionName, + $commandTester->getDisplay() + ); $commandTester = new CommandTester($command); $commandTester->execute(['command' => $command->getName(), $shardOption => 2]); - $this->assertContains('Created database ' . sys_get_temp_dir() . '/shard_2 for connection named ' . $connectionName, $commandTester->getDisplay()); + $this->assertStringContainsString( + 'Created database ' . sys_get_temp_dir() . '/shard_2 for connection named ' . $connectionName, + $commandTester->getDisplay() + ); } public function provideShardOption() : Generator diff --git a/Tests/Command/DropDatabaseDoctrineTest.php b/Tests/Command/DropDatabaseDoctrineTest.php index 3064cc0ad..aaced03d3 100644 --- a/Tests/Command/DropDatabaseDoctrineTest.php +++ b/Tests/Command/DropDatabaseDoctrineTest.php @@ -4,6 +4,7 @@ use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use Generator; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -37,7 +38,7 @@ public function testExecute(array $options) : void array_merge(['command' => $command->getName()], $options) ); - $this->assertContains( + $this->assertStringContainsString( sprintf( 'Dropped database %s for connection named %s', sys_get_temp_dir() . '/' . $dbName, @@ -52,7 +53,11 @@ public function testExecute(array $options) : void */ public function testItThrowsWhenUsingIfExistsWithAnIncompatibleDriver(array $options) : void { - static::expectException(DBALException::class); + if (class_exists(DBALException::class)) { + $this->expectException(DBALException::class); + } else { + $this->expectException(Exception::class); + } $this->testExecute($options); } @@ -77,7 +82,7 @@ public function testExecuteWithoutOptionForceWillFailWithAttentionMessage() : vo array_merge(['command' => $command->getName()]) ); - $this->assertContains( + $this->assertStringContainsString( sprintf( 'Would drop the database %s for connection named %s.', sys_get_temp_dir() . '/' . $dbName, @@ -85,7 +90,10 @@ public function testExecuteWithoutOptionForceWillFailWithAttentionMessage() : vo ), $commandTester->getDisplay() ); - $this->assertContains('Please run the operation with --force to execute', $commandTester->getDisplay()); + $this->assertStringContainsString( + 'Please run the operation with --force to execute', + $commandTester->getDisplay() + ); } public function provideForceOption() : Generator diff --git a/Tests/Command/ImportMappingDoctrineCommandTest.php b/Tests/Command/ImportMappingDoctrineCommandTest.php index 5433bd9fe..095bd10d5 100644 --- a/Tests/Command/ImportMappingDoctrineCommandTest.php +++ b/Tests/Command/ImportMappingDoctrineCommandTest.php @@ -4,6 +4,7 @@ use Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\Fixtures\TestKernel; use Doctrine\ORM\EntityManagerInterface; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; @@ -70,7 +71,11 @@ public function testExecuteXmlWithBundle() : void $expectedMetadataPath = sys_get_temp_dir() . '/import_mapping_bundle/Resources/config/doctrine/Product.orm.xml'; $this->assertFileExists($expectedMetadataPath); - $this->assertContains('"Doctrine\Bundle\DoctrineBundle\Tests\Command\Entity\Product"', file_get_contents($expectedMetadataPath), 'Metadata contains correct namespace'); + $this->assertStringContainsString( + '"Doctrine\Bundle\DoctrineBundle\Tests\Command\Entity\Product"', + file_get_contents($expectedMetadataPath), + 'Metadata contains correct namespace' + ); } public function testExecuteAnnotationsWithBundle() : void @@ -82,15 +87,17 @@ public function testExecuteAnnotationsWithBundle() : void $expectedMetadataPath = sys_get_temp_dir() . '/import_mapping_bundle/Entity/Product.php'; $this->assertFileExists($expectedMetadataPath); - $this->assertContains('namespace Doctrine\Bundle\DoctrineBundle\Tests\Command\Entity;', file_get_contents($expectedMetadataPath), 'File contains correct namespace'); + $this->assertStringContainsString( + 'namespace Doctrine\Bundle\DoctrineBundle\Tests\Command\Entity;', + file_get_contents($expectedMetadataPath), + 'File contains correct namespace' + ); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessageRegExp /The --path option is required/ - */ public function testExecuteThrowsExceptionWithNamespaceAndNoPath() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('The --path option is required'); $this->commandTester->execute(['name' => 'Some\Namespace']); } @@ -103,7 +110,11 @@ public function testExecuteXmlWithNamespace() : void $expectedMetadataPath = $this->kernel->getProjectDir() . '/config/doctrine/Product.orm.xml'; $this->assertFileExists($expectedMetadataPath); - $this->assertContains('"Some\Namespace\Entity\Product"', file_get_contents($expectedMetadataPath), 'Metadata contains correct namespace'); + $this->assertStringContainsString( + '"Some\Namespace\Entity\Product"', + file_get_contents($expectedMetadataPath), + 'Metadata contains correct namespace' + ); } public function testExecuteAnnotationsWithNamespace() : void @@ -116,7 +127,11 @@ public function testExecuteAnnotationsWithNamespace() : void $expectedMetadataPath = $this->kernel->getProjectDir() . '/src/Entity/Product.php'; $this->assertFileExists($expectedMetadataPath); - $this->assertContains('namespace Some\Namespace\Entity;', file_get_contents($expectedMetadataPath), 'Metadata contains correct namespace'); + $this->assertStringContainsString( + 'namespace Some\Namespace\Entity;', + file_get_contents($expectedMetadataPath), + 'Metadata contains correct namespace' + ); } } diff --git a/Tests/ConnectionFactoryTest.php b/Tests/ConnectionFactoryTest.php index e825c0e36..4332e4dcc 100644 --- a/Tests/ConnectionFactoryTest.php +++ b/Tests/ConnectionFactoryTest.php @@ -4,7 +4,10 @@ use Doctrine\Bundle\DoctrineBundle\ConnectionFactory; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Driver\API\ExceptionConverter; +use Doctrine\DBAL\Driver\Exception as TheDriverException; use Doctrine\DBAL\Exception\DriverException; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\MySqlPlatform; @@ -12,9 +15,6 @@ class ConnectionFactoryTest extends TestCase { - /** - * @expectedException \Doctrine\DBAL\DBALException - */ public function testContainer() : void { $typesConfig = []; @@ -23,11 +23,20 @@ public function testContainer() : void $config = null; $eventManager = null; $mappingTypes = [0]; - $exception = new DriverException('', $this->createMock(Driver\AbstractDriverException::class)); + $exception = new DriverException('', $this->createMock( + class_exists(Driver\AbstractDriverException::class) ? + Driver\AbstractDriverException::class : + TheDriverException::class + )); // put the mock into the fake driver FakeDriver::$exception = $exception; + if (class_exists(DBALException::class)) { + $this->expectException(DBALException::class); + } else { + $this->expectException(\Doctrine\DBAL\Exception::class); + } try { $factory->createConnection($params, $config, $eventManager, $mappingTypes); } catch (Exception $e) { @@ -125,6 +134,11 @@ public function getDatabase(Connection $conn) : string { return 'fake_db'; } + + public function getExceptionConverter() : ExceptionConverter + { + throw new Exception('not implemented'); + } } class FakeConnection extends Connection diff --git a/Tests/DependencyInjection/AbstractDoctrineExtensionTest.php b/Tests/DependencyInjection/AbstractDoctrineExtensionTest.php index 6762310a1..8e7b906e4 100644 --- a/Tests/DependencyInjection/AbstractDoctrineExtensionTest.php +++ b/Tests/DependencyInjection/AbstractDoctrineExtensionTest.php @@ -10,6 +10,7 @@ use Doctrine\DBAL\Schema\AbstractAsset; use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManagerInterface; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass; use Symfony\Component\Cache\Adapter\ArrayAdapter; @@ -616,17 +617,20 @@ public function testSecondLevelCache() : void $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.region.my_query_region_filelock')); $slcFactoryDef = $container->getDefinition('doctrine.orm.default_second_level_cache.default_cache_factory'); + $slcRegionsConfDef = $container->getDefinition('doctrine.orm.default_second_level_cache.regions_configuration'); $myEntityRegionDef = $container->getDefinition('doctrine.orm.default_second_level_cache.region.my_entity_region'); $loggerChainDef = $container->getDefinition('doctrine.orm.default_second_level_cache.logger_chain'); $loggerStatisticsDef = $container->getDefinition('doctrine.orm.default_second_level_cache.logger_statistics'); $myQueryRegionDef = $container->getDefinition('doctrine.orm.default_second_level_cache.region.my_query_region_filelock'); $cacheDriverDef = $container->getDefinition((string) $container->getAlias('doctrine.orm.default_second_level_cache.region_cache_driver')); $configDef = $container->getDefinition('doctrine.orm.default_configuration'); + $slcRegionsConfArgs = $slcRegionsConfDef->getArguments(); $myEntityRegionArgs = $myEntityRegionDef->getArguments(); $myQueryRegionArgs = $myQueryRegionDef->getArguments(); $slcFactoryArgs = $slcFactoryDef->getArguments(); $this->assertDICDefinitionClass($slcFactoryDef, '%doctrine.orm.second_level_cache.default_cache_factory.class%'); + $this->assertDICDefinitionClass($slcRegionsConfDef, '%doctrine.orm.second_level_cache.regions_configuration.class%'); $this->assertDICDefinitionClass($myQueryRegionDef, '%doctrine.orm.second_level_cache.filelock_region.class%'); $this->assertDICDefinitionClass($myEntityRegionDef, '%doctrine.orm.second_level_cache.default_region.class%'); $this->assertDICDefinitionClass($loggerChainDef, '%doctrine.orm.second_level_cache.logger_chain.class%'); @@ -636,6 +640,8 @@ public function testSecondLevelCache() : void $this->assertDICDefinitionMethodCallCount($slcFactoryDef, 'setRegion', [], 3); $this->assertDICDefinitionMethodCallCount($loggerChainDef, 'setLogger', [], 3); + $this->assertEquals([3600, 60], $slcRegionsConfArgs); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $slcFactoryArgs[0]); $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $slcFactoryArgs[1]); @@ -647,7 +653,10 @@ public function testSecondLevelCache() : void $this->assertEquals(600, $myEntityRegionArgs[2]); $this->assertEquals('doctrine.orm.default_second_level_cache.region.my_query_region', $myQueryRegionArgs[0]); - $this->assertContains('/doctrine/orm/slc/filelock', $myQueryRegionArgs[1]); + $this->assertStringContainsString( + '/doctrine/orm/slc/filelock', + $myQueryRegionArgs[1] + ); $this->assertEquals(60, $myQueryRegionArgs[2]); $this->assertEquals('doctrine.orm.default_second_level_cache.regions_configuration', $slcFactoryArgs[0]); @@ -1063,10 +1072,6 @@ public function testAttachLazyEntityListenerForCustomResolver() : void $this->assertTrue($container->getDefinition('entity_listener')->isPublic()); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage EntityListenerServiceResolver - */ public function testLazyEntityListenerResolverWithoutCorrectInterface() : void { if (! interface_exists(EntityManagerInterface::class)) { @@ -1080,6 +1085,8 @@ public function testLazyEntityListenerResolverWithoutCorrectInterface() : void $this->loadFromFile($container, 'orm_entity_listener_lazy_resolver_without_interface'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('EntityListenerServiceResolver'); $this->compileContainer($container); } @@ -1101,10 +1108,6 @@ public function testPrivateLazyEntityListener() : void $this->assertTrue($container->getDefinition('doctrine.orm.em1_entity_listener_resolver')->isPublic()); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessageRegExp /The service ".*" must not be abstract\./ - */ public function testAbstractEntityListener() : void { if (! interface_exists(EntityManagerInterface::class)) { @@ -1118,6 +1121,12 @@ public function testAbstractEntityListener() : void $this->loadFromFile($container, 'orm_entity_listener_abstract'); + $this->expectException(InvalidArgumentException::class); + if (method_exists($this, 'expectExceptionMessageMatches')) { + $this->expectExceptionMessageMatches('/The service ".*" must not be abstract\./'); + } else { + $this->expectExceptionMessageRegExp('/The service ".*" must not be abstract\./'); + } $this->compileContainer($container); } diff --git a/Tests/DependencyInjection/DoctrineExtensionTest.php b/Tests/DependencyInjection/DoctrineExtensionTest.php index 2300ac040..fc5434e8c 100644 --- a/Tests/DependencyInjection/DoctrineExtensionTest.php +++ b/Tests/DependencyInjection/DoctrineExtensionTest.php @@ -8,6 +8,7 @@ use Doctrine\DBAL\Driver\Connection as DriverConnection; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; +use LogicException; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Messenger\DoctrineClearEntityManagerWorkerSubscriber; use Symfony\Component\Cache\Adapter\ArrayAdapter; @@ -104,10 +105,6 @@ public function testDbalOverrideDefaultConnection() : void $this->assertEquals('foo', $container->getParameter('doctrine.default_connection'), '->load() overrides existing configuration options'); } - /** - * @expectedException \LogicException - * @expectedExceptionMessage Configuring the ORM layer requires to configure the DBAL layer as well. - */ public function testOrmRequiresDbal() : void { if (! interface_exists(EntityManagerInterface::class)) { @@ -116,6 +113,10 @@ public function testOrmRequiresDbal() : void $extension = new DoctrineExtension(); + $this->expectException(LogicException::class); + $this->expectExceptionMessage( + 'Configuring the ORM layer requires to configure the DBAL layer as well.' + ); $extension->load([['orm' => ['auto_mapping' => true]]], $this->getContainer()); } diff --git a/Tests/LazyLoadingEntityManagerInterface.php b/Tests/LazyLoadingEntityManagerInterface.php new file mode 100644 index 000000000..f1b157e67 --- /dev/null +++ b/Tests/LazyLoadingEntityManagerInterface.php @@ -0,0 +1,10 @@ +assertSame($object, $this->resolver->resolve($className)); } - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage There is no service named - */ public function testRegisterMissingServiceAndResolve() : void { $className = '\Doctrine\Bundle\DoctrineBundle\Tests\Mapping\EntityListener1'; @@ -90,6 +88,8 @@ public function testRegisterMissingServiceAndResolve() : void ->with($serviceId) ->will($this->returnValue(false)); + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('There is no service named'); $this->resolver->resolve($className); } @@ -139,12 +139,10 @@ public function testClearAll() : void $this->assertNotSame($obj2, $this->resolver->resolve($className2)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage An object was expected, but got "string". - */ public function testRegisterStringException() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('An object was expected, but got "string".'); $this->resolver->register('CompanyContractListener'); } } diff --git a/Tests/Mapping/DisconnectedMetadataFactoryTest.php b/Tests/Mapping/DisconnectedMetadataFactoryTest.php index 1ad63be64..2d5e6bba5 100644 --- a/Tests/Mapping/DisconnectedMetadataFactoryTest.php +++ b/Tests/Mapping/DisconnectedMetadataFactoryTest.php @@ -7,6 +7,7 @@ use Doctrine\Bundle\DoctrineBundle\Tests\TestCase; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadataInfo; +use RuntimeException; class DisconnectedMetadataFactoryTest extends TestCase { @@ -19,10 +20,6 @@ public static function setUpBeforeClass() : void self::markTestSkipped('This test requires ORM'); } - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage Can't find base path for "Doctrine\Bundle\DoctrineBundle\Tests\Mapping\DisconnectedMetadataFactoryTest - */ public function testCannotFindNamespaceAndPathForMetadata() : void { $class = new ClassMetadataInfo(self::class); @@ -31,6 +28,11 @@ public function testCannotFindNamespaceAndPathForMetadata() : void $registry = $this->getMockBuilder('Doctrine\Persistence\ManagerRegistry')->getMock(); $factory = new DisconnectedMetadataFactory($registry); + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage(<<<'EXCEPTION' +Can't find base path for "Doctrine\Bundle\DoctrineBundle\Tests\Mapping\DisconnectedMetadataFactoryTest +EXCEPTION + ); $factory->findNamespaceAndPathForMetadata($collection); } diff --git a/Tests/ProfilerTest.php b/Tests/ProfilerTest.php index 8276d554f..05f85f620 100644 --- a/Tests/ProfilerTest.php +++ b/Tests/ProfilerTest.php @@ -93,7 +93,7 @@ public function testRender() : void html_entity_decode($expectedEscapedSql) ); - $this->assertContains($expectedEscapedSql, $output); + $this->assertStringContainsString($expectedEscapedSql, $output); $this->assertSame(1, preg_match('/' . str_replace( ' ', diff --git a/Tests/RegistryTest.php b/Tests/RegistryTest.php index fb92feed6..ac0f272f0 100644 --- a/Tests/RegistryTest.php +++ b/Tests/RegistryTest.php @@ -8,7 +8,7 @@ use Doctrine\ORM\EntityManagerInterface; use Fixtures\Bundles\RepositoryServiceBundle\Entity\TestCustomClassRepoEntity; use Fixtures\Bundles\RepositoryServiceBundle\Repository\TestCustomClassRepoRepository; -use ProxyManager\Proxy\LazyLoadingInterface; +use InvalidArgumentException; use ProxyManager\Proxy\ProxyInterface; use stdClass; @@ -58,15 +58,13 @@ public function testGetConnection() : void $this->assertSame($conn, $registry->getConnection('default')); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Doctrine ORM Connection named "default" does not exist. - */ public function testGetUnknownConnection() : void { $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $registry = new Registry($container, [], [], 'default', 'default'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Doctrine ORM Connection named "default" does not exist.'); $registry->getConnection('default'); } @@ -106,27 +104,27 @@ public function testGetEntityManager() : void $this->assertSame($em, $registry->getManager('default')); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Doctrine ORM Manager named "default" does not exist. - */ public function testGetUnknownEntityManager() : void { $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $registry = new Registry($container, [], [], 'default', 'default'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Doctrine ORM Manager named "default" does not exist.' + ); $registry->getManager('default'); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Doctrine ORM Manager named "default" does not exist. - */ public function testResetUnknownEntityManager() : void { $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $registry = new Registry($container, [], [], 'default', 'default'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Doctrine ORM Manager named "default" does not exist.' + ); $registry->resetManager('default'); } @@ -140,7 +138,7 @@ public function testReset() : void $noProxyManager->expects($this->once()) ->method('clear'); - $proxyManager = $this->getMockBuilder([LazyLoadingInterface::class, EntityManagerInterface::class])->getMock(); + $proxyManager = $this->createMock(LazyLoadingEntityManagerInterface::class); $proxyManager->expects($this->once()) ->method('setProxyInitializer') ->with($this->isInstanceOf(Closure::class)); diff --git a/Tests/Repository/ContainerRepositoryFactoryTest.php b/Tests/Repository/ContainerRepositoryFactoryTest.php index 7cfc8796c..a4673915c 100644 --- a/Tests/Repository/ContainerRepositoryFactoryTest.php +++ b/Tests/Repository/ContainerRepositoryFactoryTest.php @@ -12,6 +12,7 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; +use RuntimeException; use stdClass; class ContainerRepositoryFactoryTest extends TestCase @@ -61,10 +62,6 @@ public function testCustomRepositoryIsReturned() : void $this->assertSame($actualRepo, $factory->getRepository($em, 'Foo\CustomNormalRepoEntity')); } - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage The service "my_repo" must implement ObjectRepository (or extend a base class, like ServiceEntityRepository). - */ public function testServiceRepositoriesMustExtendObjectRepository() : void { $repo = new stdClass(); @@ -74,6 +71,11 @@ public function testServiceRepositoriesMustExtendObjectRepository() : void $em = $this->createEntityManager(['Foo\CoolEntity' => 'my_repo']); $factory = new ContainerRepositoryFactory($container); + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage(<<<'EXCEPTION' +The service "my_repo" must implement ObjectRepository (or extend a base class, like ServiceEntityRepository). +EXCEPTION + ); $factory->getRepository($em, 'Foo\CoolEntity'); } @@ -91,10 +93,6 @@ public function testServiceRepositoriesCanNotExtendsEntityRepository() : void $this->assertSame($repo, $actualRepo); } - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage The "Doctrine\Bundle\DoctrineBundle\Tests\Repository\StubServiceRepository" entity repository implements "Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepositoryInterface", but its service could not be found. Make sure the service exists and is tagged with "doctrine.repository_service". - */ public function testRepositoryMatchesServiceInterfaceButServiceNotFound() : void { $container = $this->createContainer([]); @@ -104,13 +102,14 @@ public function testRepositoryMatchesServiceInterfaceButServiceNotFound() : void ]); $factory = new ContainerRepositoryFactory($container); + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage(<<<'EXCEPTION' +The "Doctrine\Bundle\DoctrineBundle\Tests\Repository\StubServiceRepository" entity repository implements "Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepositoryInterface", but its service could not be found. Make sure the service exists and is tagged with "doctrine.repository_service". +EXCEPTION + ); $factory->getRepository($em, 'Foo\CoolEntity'); } - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage The "Foo\CoolEntity" entity has a repositoryClass set to "not_a_real_class", but this is not a valid class. Check your class naming. If this is meant to be a service id, make sure this service exists and is tagged with "doctrine.repository_service". - */ public function testCustomRepositoryIsNotAValidClass() : void { $container = $this->createContainer([]); @@ -118,6 +117,11 @@ public function testCustomRepositoryIsNotAValidClass() : void $em = $this->createEntityManager(['Foo\CoolEntity' => 'not_a_real_class']); $factory = new ContainerRepositoryFactory($container); + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage(<<<'EXCEPTION' +The "Foo\CoolEntity" entity has a repositoryClass set to "not_a_real_class", but this is not a valid class. Check your class naming. If this is meant to be a service id, make sure this service exists and is tagged with "doctrine.repository_service". +EXCEPTION + ); $factory->getRepository($em, 'Foo\CoolEntity'); } diff --git a/Tests/Repository/ServiceEntityRepositoryTest.php b/Tests/Repository/ServiceEntityRepositoryTest.php index 4fec42a90..1fffd2a56 100644 --- a/Tests/Repository/ServiceEntityRepositoryTest.php +++ b/Tests/Repository/ServiceEntityRepositoryTest.php @@ -5,6 +5,7 @@ use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Persistence\ManagerRegistry; +use LogicException; use PHPUnit\Framework\TestCase; class ServiceEntityRepositoryTest extends TestCase @@ -18,13 +19,14 @@ public static function setUpBeforeClass() : void self::markTestSkipped('This test requires ORM'); } - /** - * @expectedException \LogicException - * @expectedExceptionMessage Could not find the entity manager for class "Doctrine\Bundle\DoctrineBundle\Tests\Repository\TestEntity". Check your Doctrine configuration to make sure it is configured to load this entity’s metadata. - */ public function testConstructorThrowsExceptionWhenNoManagerFound() : void { $registry = $this->getMockBuilder(ManagerRegistry::class)->getMock(); + $this->expectException(LogicException::class); + $this->expectExceptionMessage(<<<'EXCEPTION' +Could not find the entity manager for class "Doctrine\Bundle\DoctrineBundle\Tests\Repository\TestEntity". Check your Doctrine configuration to make sure it is configured to load this entity’s metadata. +EXCEPTION + ); new ServiceEntityRepository($registry, TestEntity::class); } } diff --git a/composer.json b/composer.json index 18082c3dd..4f71fafe5 100644 --- a/composer.json +++ b/composer.json @@ -41,7 +41,7 @@ "doctrine/coding-standard": "^6.0", "doctrine/orm": "^2.6", "ocramius/proxy-manager": "^2.1", - "phpunit/phpunit": "^7.5", + "phpunit/phpunit": "^7.5 || ^9.3", "symfony/phpunit-bridge": "^4.2", "symfony/property-info": "^4.3.3|^5.0", "symfony/proxy-manager-bridge": "^3.4|^4.3.3|^5.0",