diff --git a/.laminas-ci.json b/.laminas-ci.json index b76cebb6..bce3fa21 100644 --- a/.laminas-ci.json +++ b/.laminas-ci.json @@ -1,15 +1,5 @@ { "ignore_php_platform_requirements": { "8.1": true - }, - "additional_checks": [ - { - "name": "Psalm for psr/container v1", - "job": { - "php": "@lowest", - "dependencies": "locked", - "command": "composer require -W psr/container:^1 && vendor/bin/psalm --stats --output-format=github --no-cache" - } - } - ] + } } diff --git a/composer.json b/composer.json index 289670db..0582510b 100644 --- a/composer.json +++ b/composer.json @@ -26,18 +26,21 @@ }, "sort-packages": true, "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true + "dealerdirect/phpcodesniffer-composer-installer": true, + "composer/package-versions-deprecated": true, + "laminas/laminas-dependency-plugin": true } }, "require": { "php": "~7.4.0 || ~8.0.0 || ~8.1.0", - "composer-plugin-api": "^2.0", "laminas/laminas-stdlib": "^3.2.1", - "psr/container": "^1.1 || ^2.0.2" + "psr/container": "^1.0" }, "require-dev": { + "composer/package-versions-deprecated": "^1.0", "laminas/laminas-coding-standard": "~2.3.0", "laminas/laminas-container-config-test": "^0.6", + "laminas/laminas-dependency-plugin": "^2.1.2", "mikey179/vfsstream": "^1.6.10@alpha", "ocramius/proxy-manager": "^2.11", "phpbench/phpbench": "^1.1", @@ -47,7 +50,7 @@ "vimeo/psalm": "^4.8" }, "provide": { - "psr/container-implementation": "^1.1 || ^2.0" + "psr/container-implementation": "^1.0" }, "conflict": { "ext-psr": "*", diff --git a/composer.lock b/composer.lock index f2d02622..4b13efd2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "95886a4e7c8b9e7fbe376b2094639f27", + "content-hash": "3c3716ae3129e05fa4378e1889b98dbe", "packages": [ { "name": "laminas/laminas-stdlib", @@ -67,27 +67,22 @@ }, { "name": "psr/container", - "version": "2.0.2", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { "php": ">=7.4.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -114,9 +109,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "source": "https://github.com/php-fig/container/tree/1.1.2" }, - "time": "2021-11-05T16:47:00+00:00" + "time": "2021-11-05T16:50:12+00:00" } ], "packages-dev": [ @@ -1195,6 +1190,59 @@ ], "time": "2022-03-21T11:08:05+00:00" }, + { + "name": "laminas/laminas-dependency-plugin", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-dependency-plugin.git", + "reference": "73cfb63ddca9d6bfedad5e0a038f6d55063975a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-dependency-plugin/zipball/73cfb63ddca9d6bfedad5e0a038f6d55063975a3", + "reference": "73cfb63ddca9d6bfedad5e0a038f6d55063975a3", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1 || ^2.0", + "php": "^7.3 || ~8.0.0 || ~8.1.0" + }, + "require-dev": { + "composer/composer": "^1.9 || ^2.0", + "laminas/laminas-coding-standard": "^2.2.1", + "mikey179/vfsstream": "^1.6.10@alpha", + "phpunit/phpunit": "^9.5.5", + "psalm/plugin-phpunit": "^0.15.1", + "roave/security-advisories": "dev-master", + "vimeo/psalm": "^4.5" + }, + "type": "composer-plugin", + "extra": { + "class": "Laminas\\DependencyPlugin\\DependencyRewriterPluginDelegator" + }, + "autoload": { + "psr-4": { + "Laminas\\DependencyPlugin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Replace zendframework and zfcampus packages with their Laminas Project equivalents.", + "support": { + "issues": "https://github.com/laminas/laminas-dependency-plugin/issues", + "source": "https://github.com/laminas/laminas-dependency-plugin/tree/2.2.0" + }, + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2021-09-08T17:51:35+00:00" + }, { "name": "mikey179/vfsstream", "version": "v1.6.11-alpha.0", @@ -4823,29 +4871,37 @@ }, { "name": "symfony/service-contracts", - "version": "v1.1.2", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0" + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/191afdcb5804db960d26d8566b7e9a2843cab3a0", - "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" }, "suggest": { - "psr/container": "", "symfony/service-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -4878,9 +4934,23 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v1.1.2" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" }, - "time": "2019-05-28T07:50:59+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-30T19:17:29+00:00" }, { "name": "symfony/string", @@ -5357,8 +5427,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "~7.4.0 || ~8.0.0 || ~8.1.0", - "composer-plugin-api": "^2.0" + "php": "~7.4.0 || ~8.0.0 || ~8.1.0" }, "platform-dev": [], "platform-overrides": { diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 021c54c3..a8083863 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -16,8 +16,6 @@ bin src test - - src/AbstractUntypedContainerImplementation.php test/TestAsset/laminas-code/*.php diff --git a/psalm-baseline.xml b/psalm-baseline.xml index cd08d409..8ea35319 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -141,6 +141,10 @@ $config['services'] $config['shared'] + + $name + $name + (bool) $flag (bool) $flag diff --git a/psalm.xml.dist b/psalm.xml.dist index 05e6a1b7..d71e2eec 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -47,22 +47,6 @@ - - - - - - - - - - - - - - - - diff --git a/src/AbstractPluginManager.php b/src/AbstractPluginManager.php index 53fc86e7..fe8a85d4 100644 --- a/src/AbstractPluginManager.php +++ b/src/AbstractPluginManager.php @@ -174,7 +174,8 @@ public function get($name, ?array $options = null) } /** - * @param mixed $instance + * {@inheritDoc} + * * @psalm-assert InstanceType $instance */ public function validate($instance) diff --git a/src/AbstractTypedContainerImplementation.php b/src/AbstractTypedContainerImplementation.php deleted file mode 100644 index fe7db2c0..00000000 --- a/src/AbstractTypedContainerImplementation.php +++ /dev/null @@ -1,63 +0,0 @@ -hasService($id); - } - - /** - * Finds an entry of the container by its identifier and returns it. - * - * @param string $id Identifier of the entry to look for. - * @psalm-param string|class-string $id - * @throws NotFoundExceptionInterface No entry was found for **this** identifier. - * @throws ContainerExceptionInterface Error while retrieving the entry. - * @return mixed Entry. - */ - public function get(string $id) - { - return $this->getService($id); - } - - /** - * @internal - * - * @psalm-param string|class-string $name - */ - abstract protected function hasService(string $name): bool; - - /** - * @internal - * - * @psalm-param string|class-string $name - * @throws NotFoundExceptionInterface No entry was found for **this** identifier. - * @throws ContainerExceptionInterface Error while retrieving the entry. - * @return mixed - */ - abstract protected function getService(string $name); -} diff --git a/src/AbstractUntypedContainerImplementation.php b/src/AbstractUntypedContainerImplementation.php deleted file mode 100644 index 22a62f13..00000000 --- a/src/AbstractUntypedContainerImplementation.php +++ /dev/null @@ -1,72 +0,0 @@ -hasService($id); - } - - /** - * Finds an entry of the container by its identifier and returns it. - * - * @param string $id Identifier of the entry to look for. - * @psalm-param string|class-string $id - * - * @throws NotFoundExceptionInterface No entry was found for **this** identifier. - * @throws ContainerExceptionInterface Error while retrieving the entry. - * - * @return mixed Entry. - */ - public function get($id) - { - return $this->getService($id); - } - - /** - * @internal - * - * @psalm-param string|class-string $name - */ - abstract protected function hasService(string $name): bool; - - /** - * @internal - * - * @psalm-param string|class-string $name - * @throws NotFoundExceptionInterface No entry was found for **this** identifier. - * @throws ContainerExceptionInterface Error while retrieving the entry. - * @return mixed - */ - abstract protected function getService(string $name); -} diff --git a/src/ServiceManager.php b/src/ServiceManager.php index e0fb69fe..c87879c1 100644 --- a/src/ServiceManager.php +++ b/src/ServiceManager.php @@ -19,7 +19,6 @@ use ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy; use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; -use Psr\Container\NotFoundExceptionInterface; use function array_intersect; use function array_key_exists; @@ -62,9 +61,8 @@ * @psalm-import-type InitializersConfigurationType from ConfigInterface * @psalm-import-type LazyServicesConfigurationType from ConfigInterface * @psalm-type ServiceManagerConfiguration = array{shared_by_default?:bool}&ServiceManagerConfigurationType - * phpcs:disable WebimpressCodingStandard.PHP.CorrectClassNameCase.Invalid */ -class ServiceManager extends AbstractContainerImplementation implements ServiceLocatorInterface +class ServiceManager implements ServiceLocatorInterface { /** @var Factory\AbstractFactoryInterface[] */ protected $abstractFactories = []; @@ -189,25 +187,9 @@ public function getServiceLocator() } /** - * @internal - * - * @psalm-param string|class-string $name - */ - protected function hasService(string $name): bool - { - // Check static services and factories first to speedup the most common requests. - return $this->staticServiceOrFactoryCanCreate($name) || $this->abstractFactoryCanCreate($name); - } - - /** - * @internal - * - * @psalm-param string|class-string $name - * @throws NotFoundExceptionInterface No entry was found for **this** identifier. - * @throws ContainerExceptionInterface Error while retrieving the entry. - * @return mixed + * {@inheritDoc} */ - protected function getService(string $name) + public function get($name) { // We start by checking if we have cached the requested service; // this is the fastest method. @@ -275,6 +257,18 @@ public function build($name, ?array $options = null) return $this->doCreate($name, $options); } + /** + * {@inheritDoc} + * + * @param string|class-string $name + * @return bool + */ + public function has($name) + { + // Check static services and factories first to speedup the most common requests. + return $this->staticServiceOrFactoryCanCreate($name) || $this->abstractFactoryCanCreate($name); + } + /** * Indicate whether or not the instance is immutable. * diff --git a/src/autoload.php b/src/autoload.php index 1e5fbfc1..76bd64e0 100644 --- a/src/autoload.php +++ b/src/autoload.php @@ -3,9 +3,6 @@ declare(strict_types=1); -namespace Laminas\ServiceManager; - -use Composer\InstalledVersions; use Interop\Container\Containerinterface as InteropContainerInterface; use Interop\Container\Exception\ContainerException as InteropContainerException; use Interop\Container\Exception\NotFoundException as InteropNotFoundException; @@ -13,11 +10,6 @@ use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; -use function assert; -use function class_alias; -use function interface_exists; -use function version_compare; - if (! interface_exists(InteropContainerInterface::class, false)) { class_alias(ContainerInterface::class, InteropContainerInterface::class); } @@ -27,16 +19,3 @@ class_alias(ContainerExceptionInterface::class, InteropContainerException::class if (! interface_exists(InteropNotFoundException::class, false)) { class_alias(NotFoundExceptionInterface::class, InteropNotFoundException::class); } - -$installedContainerVersion = InstalledVersions::getVersion('psr/container'); - -assert( - $installedContainerVersion !== null, - 'psr/container is required by `composer.json` and therefore this method should not return `null`.' -); - -if (version_compare($installedContainerVersion, '2', '<')) { - class_alias(AbstractUntypedContainerImplementation::class, AbstractContainerImplementation::class); -} else { - class_alias(AbstractTypedContainerImplementation::class, AbstractContainerImplementation::class); -} diff --git a/test/AbstractFactory/ReflectionBasedAbstractFactoryTest.php b/test/AbstractFactory/ReflectionBasedAbstractFactoryTest.php index b406e333..015d0668 100644 --- a/test/AbstractFactory/ReflectionBasedAbstractFactoryTest.php +++ b/test/AbstractFactory/ReflectionBasedAbstractFactoryTest.php @@ -7,20 +7,23 @@ use ArrayAccess; use Laminas\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory; use Laminas\ServiceManager\Exception\ServiceNotFoundException; -use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; +use Prophecy\Prophecy\ObjectProphecy; use Psr\Container\ContainerInterface; use function sprintf; class ReflectionBasedAbstractFactoryTest extends TestCase { - /** @var MockObject&ContainerInterface */ - private ContainerInterface $container; + use ProphecyTrait; + + /** @var ObjectProphecy */ + private ObjectProphecy $container; public function setUp(): void { - $this->container = $this->createMock(ContainerInterface::class); + $this->container = $this->prophesize(ContainerInterface::class); } public function nonClassRequestedNames(): array @@ -36,14 +39,14 @@ public function nonClassRequestedNames(): array public function testCanCreateReturnsFalseForNonClassRequestedNames(string $requestedName): void { $factory = new ReflectionBasedAbstractFactory(); - $this->assertFalse($factory->canCreate($this->container, $requestedName)); + $this->assertFalse($factory->canCreate($this->container->reveal(), $requestedName)); } public function testCanCreateReturnsFalseWhenConstructorIsPrivate(): void { $this->assertFalse( (new ReflectionBasedAbstractFactory())->canCreate( - $this->container, + $this->container->reveal(), TestAsset\ClassWithPrivateConstructor::class ), 'ReflectionBasedAbstractFactory should not be able to instantiate a class with a private constructor' @@ -54,7 +57,7 @@ public function testCanCreateReturnsTrueWhenClassHasNoConstructor(): void { $this->assertTrue( (new ReflectionBasedAbstractFactory())->canCreate( - $this->container, + $this->container->reveal(), TestAsset\ClassWithNoConstructor::class ), 'ReflectionBasedAbstractFactory should be able to instantiate a class without a constructor' @@ -64,24 +67,21 @@ public function testCanCreateReturnsTrueWhenClassHasNoConstructor(): void public function testFactoryInstantiatesClassDirectlyIfItHasNoConstructor(): void { $factory = new ReflectionBasedAbstractFactory(); - $instance = $factory($this->container, TestAsset\ClassWithNoConstructor::class); + $instance = $factory($this->container->reveal(), TestAsset\ClassWithNoConstructor::class); $this->assertInstanceOf(TestAsset\ClassWithNoConstructor::class, $instance); } public function testFactoryInstantiatesClassDirectlyIfConstructorHasNoArguments(): void { $factory = new ReflectionBasedAbstractFactory(); - $instance = $factory($this->container, TestAsset\ClassWithEmptyConstructor::class); + $instance = $factory($this->container->reveal(), TestAsset\ClassWithEmptyConstructor::class); $this->assertInstanceOf(TestAsset\ClassWithEmptyConstructor::class, $instance); } public function testFactoryRaisesExceptionWhenUnableToResolveATypeHintedService(): void { - $this->container - ->method('has') - ->withConsecutive(['config'], [TestAsset\SampleInterface::class]) - ->willReturn(false); - + $this->container->has(TestAsset\SampleInterface::class)->willReturn(false); + $this->container->has('config')->willReturn(false); $factory = new ReflectionBasedAbstractFactory(); $this->expectException(ServiceNotFoundException::class); $this->expectExceptionMessage(sprintf( @@ -89,7 +89,7 @@ public function testFactoryRaisesExceptionWhenUnableToResolveATypeHintedService( TestAsset\ClassWithTypeHintedConstructorParameter::class, TestAsset\SampleInterface::class )); - $factory($this->container, TestAsset\ClassWithTypeHintedConstructorParameter::class); + $factory($this->container->reveal(), TestAsset\ClassWithTypeHintedConstructorParameter::class); } public function testFactoryRaisesExceptionForScalarParameters(): void @@ -100,57 +100,45 @@ public function testFactoryRaisesExceptionForScalarParameters(): void 'Unable to create service "%s"; unable to resolve parameter "foo" to a class, interface, or array type', TestAsset\ClassWithScalarParameters::class )); - $factory($this->container, TestAsset\ClassWithScalarParameters::class); + $factory($this->container->reveal(), TestAsset\ClassWithScalarParameters::class); } public function testFactoryInjectsConfigServiceForConfigArgumentsTypeHintedAsArray(): void { $config = ['foo' => 'bar']; - $this->container->method('has')->with('config')->willReturn(true); - $this->container->method('get')->with('config')->willReturn($config); + $this->container->has('config')->willReturn(true); + $this->container->get('config')->willReturn($config); $factory = new ReflectionBasedAbstractFactory(); - $instance = $factory($this->container, TestAsset\ClassAcceptingConfigToConstructor::class); + $instance = $factory($this->container->reveal(), TestAsset\ClassAcceptingConfigToConstructor::class); $this->assertInstanceOf(TestAsset\ClassAcceptingConfigToConstructor::class, $instance); $this->assertEquals($config, $instance->config); } public function testFactoryCanInjectKnownTypeHintedServices(): void { - $sample = $this->createStub(TestAsset\SampleInterface::class); - $this->container - ->method('has') - ->withConsecutive(['config'], [TestAsset\SampleInterface::class]) - ->willReturnOnConsecutiveCalls(false, true); - - $this->container - ->expects(self::once()) - ->method('get') - ->with(TestAsset\SampleInterface::class) - ->willReturn($sample); + $sample = $this->prophesize(TestAsset\SampleInterface::class)->reveal(); + $this->container->has('config')->willReturn(false); + $this->container->has(TestAsset\SampleInterface::class)->willReturn(true); + $this->container->get(TestAsset\SampleInterface::class)->willReturn($sample); $factory = new ReflectionBasedAbstractFactory(); - $instance = $factory($this->container, TestAsset\ClassWithTypeHintedConstructorParameter::class); + $instance = $factory($this->container->reveal(), TestAsset\ClassWithTypeHintedConstructorParameter::class); $this->assertInstanceOf(TestAsset\ClassWithTypeHintedConstructorParameter::class, $instance); $this->assertSame($sample, $instance->sample); } public function testFactoryResolvesTypeHintsForServicesToWellKnownServiceNames(): void { - $this->container - ->method('has') - ->withConsecutive(['config'], ['ValidatorManager']) - ->willReturnOnConsecutiveCalls(false, true); + $this->container->has('config')->willReturn(false); - $validators = $this->createStub(TestAsset\ValidatorPluginManager::class); - $this->container - ->method('get') - ->with('ValidatorManager') - ->willReturn($validators); + $validators = $this->prophesize(TestAsset\ValidatorPluginManager::class)->reveal(); + $this->container->has('ValidatorManager')->willReturn(true); + $this->container->get('ValidatorManager')->willReturn($validators); $factory = new ReflectionBasedAbstractFactory([TestAsset\ValidatorPluginManager::class => 'ValidatorManager']); $instance = $factory( - $this->container, + $this->container->reveal(), TestAsset\ClassAcceptingWellKnownServicesAsConstructorParameters::class ); $this->assertInstanceOf( @@ -162,22 +150,20 @@ public function testFactoryResolvesTypeHintsForServicesToWellKnownServiceNames() public function testFactoryCanSupplyAMixOfParameterTypes(): void { - $validators = $this->createStub(TestAsset\ValidatorPluginManager::class); - $this->container - ->method('has') - ->withConsecutive(['config'], [TestAsset\SampleInterface::class], ['ValidatorManager']) - ->willReturn(true); + $validators = $this->prophesize(TestAsset\ValidatorPluginManager::class)->reveal(); + $this->container->has('ValidatorManager')->willReturn(true); + $this->container->get('ValidatorManager')->willReturn($validators); - $sample = $this->createStub(TestAsset\SampleInterface::class); - $config = ['foo' => 'bar']; + $sample = $this->prophesize(TestAsset\SampleInterface::class)->reveal(); + $this->container->has(TestAsset\SampleInterface::class)->willReturn(true); + $this->container->get(TestAsset\SampleInterface::class)->willReturn($sample); - $this->container - ->method('get') - ->withConsecutive([TestAsset\SampleInterface::class], ['ValidatorManager'], ['config']) - ->willReturnOnConsecutiveCalls($sample, $validators, $config); + $config = ['foo' => 'bar']; + $this->container->has('config')->willReturn(true); + $this->container->get('config')->willReturn($config); $factory = new ReflectionBasedAbstractFactory([TestAsset\ValidatorPluginManager::class => 'ValidatorManager']); - $instance = $factory($this->container, TestAsset\ClassWithMixedConstructorParameters::class); + $instance = $factory($this->container->reveal(), TestAsset\ClassWithMixedConstructorParameters::class); $this->assertInstanceOf(TestAsset\ClassWithMixedConstructorParameters::class, $instance); $this->assertEquals($config, $instance->config); @@ -188,10 +174,10 @@ public function testFactoryCanSupplyAMixOfParameterTypes(): void public function testFactoryWillUseDefaultValueWhenPresentForScalarArgument(): void { - $this->container->method('has')->with('config')->willReturn(false); + $this->container->has('config')->willReturn(false); $factory = new ReflectionBasedAbstractFactory(); $instance = $factory( - $this->container, + $this->container->reveal(), TestAsset\ClassWithScalarDependencyDefiningDefaultValue::class ); $this->assertInstanceOf(TestAsset\ClassWithScalarDependencyDefiningDefaultValue::class, $instance); @@ -203,13 +189,11 @@ public function testFactoryWillUseDefaultValueWhenPresentForScalarArgument(): vo */ public function testFactoryWillUseDefaultValueForTypeHintedArgument(): void { - $this->container - ->method('has') - ->withConsecutive(['config'], [ArrayAccess::class]) - ->willReturn(false); + $this->container->has('config')->willReturn(false); + $this->container->has(ArrayAccess::class)->willReturn(false); $factory = new ReflectionBasedAbstractFactory(); $instance = $factory( - $this->container, + $this->container->reveal(), TestAsset\ClassWithTypehintedDefaultValue::class ); $this->assertInstanceOf(TestAsset\ClassWithTypehintedDefaultValue::class, $instance); diff --git a/test/AbstractPluginManagerTest.php b/test/AbstractPluginManagerTest.php index 4dfe9c43..15801d83 100644 --- a/test/AbstractPluginManagerTest.php +++ b/test/AbstractPluginManagerTest.php @@ -17,6 +17,7 @@ use LaminasTest\ServiceManager\TestAsset\SimplePluginManager; use LaminasTest\ServiceManager\TestAsset\V2v3PluginManager; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Psr\Container\ContainerInterface; use stdClass; @@ -32,6 +33,7 @@ class AbstractPluginManagerTest extends TestCase { use CommonServiceLocatorBehaviorsTrait; + use ProphecyTrait; public function createContainer(array $config = []): ServiceManager { @@ -41,7 +43,8 @@ public function createContainer(array $config = []): ServiceManager public function testInjectCreationContextInFactories(): void { - $invokableFactory = $this->createMock(FactoryInterface::class); + $invokableFactory = $this->getMockBuilder(FactoryInterface::class) + ->getMock(); $config = [ 'factories' => [ @@ -49,7 +52,8 @@ public function testInjectCreationContextInFactories(): void ], ]; - $container = $this->createStub(ContainerInterface::class); + $container = $this->getMockBuilder(ContainerInterface::class) + ->getMock(); $pluginManager = new SimplePluginManager($container, $config); $invokableFactory->expects($this->once()) @@ -71,7 +75,8 @@ public function testValidateInstance(): void ], ]; - $container = $this->createStub(ContainerInterface::class); + $container = $this->getMockBuilder(ContainerInterface::class) + ->getMock(); $pluginManager = new SimplePluginManager($container, $config); // Assert no exception is triggered because the plugin manager validate ObjectWithOptions @@ -90,7 +95,8 @@ public function testCachesInstanceByDefaultIfNoOptionsArePassed(): void ], ]; - $container = $this->createStub(ContainerInterface::class); + $container = $this->getMockBuilder(ContainerInterface::class) + ->getMock(); $pluginManager = new SimplePluginManager($container, $config); $first = $pluginManager->get(InvokableObject::class); @@ -122,7 +128,8 @@ public function testReturnsDiscreteInstancesIfOptionsAreProvidedRegardlessOfShar ]; $options = ['foo' => 'bar']; - $container = $this->createStub(ContainerInterface::class); + $container = $this->getMockBuilder(ContainerInterface::class) + ->getMock(); $pluginManager = new SimplePluginManager($container, $config); $first = $pluginManager->get(InvokableObject::class, $options); @@ -228,13 +235,13 @@ public function testPassingNoInitialConstructorArgumentSetsPluginManagerAsCreati */ public function testCanPassConfigInterfaceAsFirstConstructorArgumentWithDeprecationNotice(): void { - $config = $this->createStub(ConfigInterface::class); - $config->method('toArray')->willReturn([]); + $config = $this->prophesize(ConfigInterface::class); + $config->toArray()->willReturn([]); set_error_handler(function ($errno, $errstr) { $this->assertEquals(E_USER_DEPRECATED, $errno); }, E_USER_DEPRECATED); - $pluginManager = new TestAsset\LenientPluginManager($config); + $pluginManager = new TestAsset\LenientPluginManager($config->reveal()); restore_error_handler(); $this->assertSame($pluginManager, $pluginManager->getCreationContext()); @@ -271,15 +278,13 @@ public function testPassingNonContainerNonConfigNonNullFirstConstructorArgumentR */ public function testPassingConfigInstanceAsFirstConstructorArgumentSkipsSecondArgumentWithDeprecationNotice(): void { - $config = $this->createMock(ConfigInterface::class); - $config - ->method('toArray') - ->willReturn(['services' => [self::class => $this]]); + $config = $this->prophesize(ConfigInterface::class); + $config->toArray()->willReturn(['services' => [self::class => $this]]); set_error_handler(function ($errno, $errstr) { $this->assertEquals(E_USER_DEPRECATED, $errno); }, E_USER_DEPRECATED); - $pluginManager = new TestAsset\LenientPluginManager($config, ['services' => [self::class => []]]); + $pluginManager = new TestAsset\LenientPluginManager($config->reveal(), ['services' => [self::class => []]]); restore_error_handler(); $this->assertSame($this, $pluginManager->get(self::class)); @@ -373,18 +378,12 @@ public function testAbstractFactoryGetsCreationContext(): void { $serviceManager = new ServiceManager(); $pluginManager = new SimplePluginManager($serviceManager); - $abstractFactory = $this->createMock(AbstractFactoryInterface::class); - $abstractFactory - ->method('canCreate') - ->with($serviceManager, 'foo') + $abstractFactory = $this->prophesize(AbstractFactoryInterface::class); + $abstractFactory->canCreate($serviceManager, 'foo') ->willReturn(true); - - $abstractFactory - ->method('__invoke') - ->with($serviceManager, 'foo', null) + $abstractFactory->__invoke($serviceManager, 'foo', null) ->willReturn(new InvokableObject()); - - $pluginManager->addAbstractFactory($abstractFactory); + $pluginManager->addAbstractFactory($abstractFactory->reveal()); $this->assertInstanceOf(InvokableObject::class, $pluginManager->get('foo')); } diff --git a/test/ConfigTest.php b/test/ConfigTest.php index a157f791..1e456005 100644 --- a/test/ConfigTest.php +++ b/test/ConfigTest.php @@ -7,12 +7,15 @@ use Laminas\ServiceManager\Config; use Laminas\ServiceManager\ServiceManager; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; /** * @covers Laminas\ServiceManager\Config */ class ConfigTest extends TestCase { + use ProphecyTrait; + public function testMergeArrays(): void { $config = [ @@ -100,12 +103,12 @@ public function testPassesKnownServiceConfigKeysToServiceManagerWithConfigMethod 'baz' => 'bat', ]; - $services = $this->createMock(ServiceManager::class); - $services->method('configure')->with($expected)->willReturn('CALLED'); + $services = $this->prophesize(ServiceManager::class); + $services->configure($expected)->willReturn('CALLED'); /** @psalm-suppress InvalidArgument Keeping this invalid configuration to ensure BC compatibility. */ $configuration = new Config($config); - $this->assertEquals('CALLED', $configuration->configureServiceManager($services)); + $this->assertEquals('CALLED', $configuration->configureServiceManager($services->reveal())); return [ 'array' => $expected,