Skip to content
This repository has been archived by the owner on Jan 12, 2020. It is now read-only.

Commit

Permalink
Add Resolver (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
yoanm authored Apr 3, 2018
1 parent be406e8 commit aa5120a
Show file tree
Hide file tree
Showing 9 changed files with 306 additions and 6 deletions.
92 changes: 87 additions & 5 deletions features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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;
}
}
10 changes: 10 additions & 0 deletions features/bootstrap/resolver.feature
Original file line number Diff line number Diff line change
@@ -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"
Empty file removed src/.gitkeep
Empty file.
29 changes: 29 additions & 0 deletions src/App/Resolver/DefaultServiceNameResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
namespace Yoanm\JsonRpcServerPsr11Resolver\App\Resolver;

use Yoanm\JsonRpcServerPsr11Resolver\Domain\Model\ServiceNameResolverInterface;

/**
* Class ContainerMethodResolver
*/
class DefaultServiceNameResolver implements ServiceNameResolverInterface
{
/** @var string */
private $prefix = '';

/**
* @param string $prefix
*/
public function __construct(string $prefix = '')
{
$this->prefix = $prefix;
}

/**
* {@inheritdoc}
*/
public function resolve(string $methodName) : string
{
return $this->prefix.$methodName;
}
}
15 changes: 15 additions & 0 deletions src/Domain/Model/ServiceNameResolverInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
namespace Yoanm\JsonRpcServerPsr11Resolver\Domain\Model;

/**
* Interface ServiceNameResolverInterface
*/
interface ServiceNameResolverInterface
{
/**
* @param string $methodName
*
* @return string The corresponding service name
*/
public function resolve(string $methodName) : string;
}
40 changes: 40 additions & 0 deletions src/Infra/Resolver/ContainerMethodResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
namespace Yoanm\JsonRpcServerPsr11Resolver\Infra\Resolver;

use Psr\Container\ContainerInterface;
use Yoanm\JsonRpcServer\Domain\Exception\JsonRpcMethodNotFoundException;
use Yoanm\JsonRpcServer\Domain\Model\JsonRpcMethodInterface;
use Yoanm\JsonRpcServer\Domain\Model\MethodResolverInterface;
use Yoanm\JsonRpcServerPsr11Resolver\Domain\Model\ServiceNameResolverInterface;

/**
* Class ContainerMethodResolver
*/
class ContainerMethodResolver implements MethodResolverInterface
{
/** @var ContainerInterface */
private $container;
/** @var ServiceNameResolverInterface */
private $serviceNameResolver;

public function __construct(
ContainerInterface $container,
ServiceNameResolverInterface $serviceNameResolver
) {
$this->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);
}
}
1 change: 0 additions & 1 deletion tests/Functional/.gitkeep

This file was deleted.

36 changes: 36 additions & 0 deletions tests/Functional/App/Resolver/DefaultServiceNameResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
namespace Tests\Functional\App\Resolver;

use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Yoanm\JsonRpcServerPsr11Resolver\App\Resolver\DefaultServiceNameResolver;

/**
* @covers \Yoanm\JsonRpcServerPsr11Resolver\App\Resolver\DefaultServiceNameResolver
*/
class DefaultServiceNameResolverTest extends TestCase
{
public function testShouldDoNothingByDefault()
{
$serviceName = 'my-service-name';
$resolver = new DefaultServiceNameResolver();

$this->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)
);
}
}
89 changes: 89 additions & 0 deletions tests/Functional/Infra/Resolver/ContainerMethodResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
namespace Tests\Functional\Infra\Resolver;

use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\Container\ContainerInterface;
use Yoanm\JsonRpcServer\Domain\Exception\JsonRpcMethodNotFoundException;
use Yoanm\JsonRpcServer\Domain\Model\JsonRpcMethodInterface;
use Yoanm\JsonRpcServerPsr11Resolver\Domain\Model\ServiceNameResolverInterface;
use Yoanm\JsonRpcServerPsr11Resolver\Infra\Resolver\ContainerMethodResolver;

/**
* @covers \Yoanm\JsonRpcServerPsr11Resolver\Infra\Resolver\ContainerMethodResolver
*/
class ContainerMethodResolverTest extends TestCase
{
/** @var ContainerMethodResolver */
private $resolver;

/** @var ContainerInterface|ObjectProphecy */
private $container;
/** @var ServiceNameResolverInterface|ObjectProphecy */
private $serviceNameResolver;

public function setUp()
{
$this->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;
}
}
}

0 comments on commit aa5120a

Please sign in to comment.