From aa5120aa8ca873bb16fc5e30e00c2efe6d2e64c8 Mon Sep 17 00:00:00 2001 From: Yo Date: Tue, 3 Apr 2018 23:47:22 +0200 Subject: [PATCH] Add Resolver (#1) --- features/bootstrap/FeatureContext.php | 92 ++++++++++++++++++- features/bootstrap/resolver.feature | 10 ++ src/.gitkeep | 0 .../Resolver/DefaultServiceNameResolver.php | 29 ++++++ .../Model/ServiceNameResolverInterface.php | 15 +++ .../Resolver/ContainerMethodResolver.php | 40 ++++++++ tests/Functional/.gitkeep | 1 - .../DefaultServiceNameResolverTest.php | 36 ++++++++ .../Resolver/ContainerMethodResolverTest.php | 89 ++++++++++++++++++ 9 files changed, 306 insertions(+), 6 deletions(-) create mode 100644 features/bootstrap/resolver.feature delete mode 100644 src/.gitkeep create mode 100644 src/App/Resolver/DefaultServiceNameResolver.php create mode 100644 src/Domain/Model/ServiceNameResolverInterface.php create mode 100644 src/Infra/Resolver/ContainerMethodResolver.php delete mode 100644 tests/Functional/.gitkeep create mode 100644 tests/Functional/App/Resolver/DefaultServiceNameResolverTest.php create mode 100644 tests/Functional/Infra/Resolver/ContainerMethodResolverTest.php diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 902395f..cae7bbd 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -2,19 +2,36 @@ namespace Tests\Functional\BehatContext; use Behat\Behat\Context\Context; -use Behat\Gherkin\Node\PyStringNode; use PHPUnit\Framework\Assert; use Prophecy\Argument; -use Tests\Functional\BehatContext\App\BehatMethodResolver; -use Tests\Functional\BehatContext\App\FakeEndpointCreator; -use Yoanm\JsonRpcServer\Domain\Model\MethodResolverInterface; -use Yoanm\JsonRpcServer\Infra\Endpoint\JsonRpcEndpoint; +use Prophecy\Prophecy\ObjectProphecy; +use Prophecy\Prophet; +use Psr\Container\ContainerInterface; +use Yoanm\JsonRpcServer\Domain\Exception\JsonRpcMethodNotFoundException; +use Yoanm\JsonRpcServer\Domain\Model\JsonRpcMethodInterface; +use Yoanm\JsonRpcServerPsr11Resolver\App\Resolver\DefaultServiceNameResolver; +use Yoanm\JsonRpcServerPsr11Resolver\Infra\Resolver\ContainerMethodResolver; /** * Defines application features from the specific context. */ class FeatureContext implements Context { + /** @var ContainerMethodResolver */ + private $methodResolver; + + /** @var ObjectProphecy[] */ + private $prophesizedMethodList = []; + /** @var JsonRpcMethodInterface|ObjectProphecy|null */ + private $lastMethod; + /** @var JsonRpcMethodNotFoundException|null */ + private $lastException; + + /** @var Prophet */ + private $prophet; + /** @var ObjectProphecy|ContainerInterface */ + private $container; + /** * Initializes context. * @@ -24,5 +41,70 @@ class FeatureContext implements Context */ public function __construct() { + $this->prophet = new Prophet(); + + $this->container = $this->prophet->prophesize(ContainerInterface::class); + // By default return false + $this->container->has(Argument::cetera())->willReturn(false); + + $this->methodResolver = new ContainerMethodResolver( + $this->container->reveal(), + new DefaultServiceNameResolver() + ); + } + + /** + * @Given there is a method named :methodName + */ + public function givenThereIsAMethodNamed($methodName) + { + $this->prophesizedMethodList[$methodName] = $this->prophesizeMethod($methodName); + } + + /** + * @When I ask for :methodName method + */ + public function whenIAskForMethod($methodName) + { + $this->lastException = $this->lastMethod = null; + try { + $this->lastMethod = $this->methodResolver->resolve($methodName); + } catch (JsonRpcMethodNotFoundException $exception) { + $this->lastException = $exception; + } + } + + /** + * @Then I should have :methodName method + */ + public function thenIShouldHaveMethod($methodName) + { + Assert::assertSame( + $this->prophesizedMethodList[$methodName]->reveal(), + $this->lastMethod + ); + } + /** + * @Then I should have a JSON-RPC exception with code :errorCode + */ + public function thenIShouldHaveAJsonRpcExceptionWithCode($errorCode) + { + Assert::assertInstanceOf(JsonRpcMethodNotFoundException::class, $this->lastException); + Assert::assertSame((int)$errorCode, $this->lastException->getErrorCode()); + } + + /** + * @param string $methodName + * + * @return ObjectProphecy + */ + private function prophesizeMethod(string $methodName) + { + $method = $this->prophet->prophesize(JsonRpcMethodInterface::class); + + $this->container->has($methodName)->willReturn(true); + $this->container->get($methodName)->willReturn($method->reveal()); + + return $method; } } diff --git a/features/bootstrap/resolver.feature b/features/bootstrap/resolver.feature new file mode 100644 index 0000000..5a8a7b6 --- /dev/null +++ b/features/bootstrap/resolver.feature @@ -0,0 +1,10 @@ +Feature: Resolver + + Scenario: Should return the requested method + Given there is a method named "my-method" + When I ask for "my-method" method + Then I should have "my-method" method + + Scenario: Should throw an exception if requested method does not exist + When I ask for "not-existing-method" method + Then I should have a JSON-RPC exception with code "-32601" diff --git a/src/.gitkeep b/src/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/App/Resolver/DefaultServiceNameResolver.php b/src/App/Resolver/DefaultServiceNameResolver.php new file mode 100644 index 0000000..087f538 --- /dev/null +++ b/src/App/Resolver/DefaultServiceNameResolver.php @@ -0,0 +1,29 @@ +prefix = $prefix; + } + + /** + * {@inheritdoc} + */ + public function resolve(string $methodName) : string + { + return $this->prefix.$methodName; + } +} diff --git a/src/Domain/Model/ServiceNameResolverInterface.php b/src/Domain/Model/ServiceNameResolverInterface.php new file mode 100644 index 0000000..f0dba74 --- /dev/null +++ b/src/Domain/Model/ServiceNameResolverInterface.php @@ -0,0 +1,15 @@ +container = $container; + $this->serviceNameResolver = $serviceNameResolver; + } + + /** + * {@inheritdoc} + */ + public function resolve(string $methodName) : JsonRpcMethodInterface + { + $serviceName = $this->serviceNameResolver->resolve($methodName); + if (!$this->container->has($serviceName)) { + throw new JsonRpcMethodNotFoundException($methodName); + } + + return $this->container->get($serviceName); + } +} diff --git a/tests/Functional/.gitkeep b/tests/Functional/.gitkeep deleted file mode 100644 index 8b13789..0000000 --- a/tests/Functional/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/Functional/App/Resolver/DefaultServiceNameResolverTest.php b/tests/Functional/App/Resolver/DefaultServiceNameResolverTest.php new file mode 100644 index 0000000..2b68287 --- /dev/null +++ b/tests/Functional/App/Resolver/DefaultServiceNameResolverTest.php @@ -0,0 +1,36 @@ +assertSame( + $serviceName, + $resolver->resolve($serviceName) + ); + } + + + public function testShouldPrependPrefixBeforeServiceName() + { + $prefix = 'my-prefix'; + $serviceName = 'my-service-name'; + $resolver = new DefaultServiceNameResolver($prefix); + + $this->assertSame( + $prefix.$serviceName, + $resolver->resolve($serviceName) + ); + } +} diff --git a/tests/Functional/Infra/Resolver/ContainerMethodResolverTest.php b/tests/Functional/Infra/Resolver/ContainerMethodResolverTest.php new file mode 100644 index 0000000..46eba2a --- /dev/null +++ b/tests/Functional/Infra/Resolver/ContainerMethodResolverTest.php @@ -0,0 +1,89 @@ +container = $this->prophesize(ContainerInterface::class); + $this->serviceNameResolver = $this->prophesize(ServiceNameResolverInterface::class); + + $this->resolver = new ContainerMethodResolver( + $this->container->reveal(), + $this->serviceNameResolver->reveal() + ); + } + + + public function testShouldResolveServiceNameAndLoadItFromContainer() + { + $methodName = 'my-method-name'; + $serviceName = 'my-service-name'; + + $method = $this->prophesize(JsonRpcMethodInterface::class); + + $this->serviceNameResolver->resolve($methodName) + ->willReturn($serviceName) + ->shouldBeCalled(); + + $this->container->has($serviceName) + ->willReturn(true) + ->shouldBeCalled(); + + $this->container->get($serviceName) + ->willReturn($method->reveal()) + ->shouldBeCalled(); + + $this->assertSame( + $method->reveal(), + $this->resolver->resolve($methodName) + ); + } + + public function testShouldThrowAnExceptionIsMethodDoesNotExist() + { + $methodName = 'my-method-name'; + $serviceName = 'my-service-name'; + + $this->serviceNameResolver->resolve($methodName) + ->willReturn($serviceName) + ->shouldBeCalled(); + + $this->container->has($serviceName) + ->willReturn(false) + ->shouldBeCalled(); + + $this->expectException(JsonRpcMethodNotFoundException::class); + + try { + $this->resolver->resolve($methodName); + } catch (JsonRpcMethodNotFoundException $e) { + $this->assertSame( + $methodName, + $e->getMethodName() + ); + + throw $e; + } + } +}