add tests for client and url class
This commit is contained in:
parent
740b14f868
commit
3a3a940a01
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.idea
|
||||
.phpunit.result.cache
|
||||
build
|
||||
composer.lock
|
||||
vendor
|
@ -18,7 +18,7 @@ abstract class ApiTestCase extends TestCase
|
||||
* @return mixed
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function callMethod(object $object, string $methodName, array $arguments = array()): mixed
|
||||
public function callMethod(object $object, string $methodName, array $arguments = array())
|
||||
{
|
||||
$class = new ReflectionClass($object);
|
||||
$method = $class->getMethod($methodName);
|
||||
@ -50,7 +50,7 @@ abstract class ApiTestCase extends TestCase
|
||||
* @return mixed
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function getValue(object $object, string $valueName): mixed
|
||||
public function getValue(object $object, string $valueName)
|
||||
{
|
||||
$reflection = new ReflectionClass($object);
|
||||
$property = $reflection->getProperty($valueName);
|
||||
|
@ -1,16 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This Software is the property of Data Development and is protected
|
||||
* by copyright law - it is NOT Freeware.
|
||||
* Any unauthorized use of this software without a valid license
|
||||
* is a violation of the license agreement and will be prosecuted by
|
||||
* civil and criminal law.
|
||||
* http://www.shopmodule.com
|
||||
*
|
||||
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
|
||||
* @link http://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace D3\LinkmobilityClient\Tests;
|
||||
|
||||
use Assert\InvalidArgumentException;
|
||||
use D3\LinkmobilityClient\Client;
|
||||
use D3\LinkmobilityClient\Exceptions\ApiException;
|
||||
use D3\LinkmobilityClient\Request\RequestInterface;
|
||||
use D3\LinkmobilityClient\Response\Response;
|
||||
use D3\LinkmobilityClient\Response\ResponseInterface;
|
||||
use D3\LinkmobilityClient\SMS\TextRequest;
|
||||
use D3\LinkmobilityClient\Url;
|
||||
use D3\LinkmobilityClient\UrlInterface;
|
||||
use GuzzleHttp\Client as GuzzleClient;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Psr\Http\Message\ResponseInterface as MessageResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Log\AbstractLogger;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use ReflectionException;
|
||||
|
||||
class ApiClientTest extends ApiTestCase
|
||||
class ClientTest extends ApiTestCase
|
||||
{
|
||||
public string $fixtureApiKey = 'fixtureApiKey';
|
||||
/** @var ApiClient */
|
||||
/** @var Client */
|
||||
public Client $api;
|
||||
public string $jsonFixture = 'json_content';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setUp():void
|
||||
{
|
||||
parent::setUp();
|
||||
@ -19,10 +53,234 @@ class ApiClientTest extends ApiTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
*/
|
||||
public function testRun()
|
||||
public function tearDown(): void
|
||||
{
|
||||
$this->assertTrue(true);
|
||||
parent::tearDown();
|
||||
|
||||
unset($this->api);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider constructPassedArgumentsDataProvider
|
||||
* @param $apiKey
|
||||
* @param $apiUrl
|
||||
* @param $apiClient
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function testConstruct($apiKey, $apiUrl, $apiClient)
|
||||
{
|
||||
$api = new Client($apiKey, $apiUrl, $apiClient);
|
||||
|
||||
$this->assertSame(
|
||||
$this->getValue($api, 'accessToken'),
|
||||
$apiKey
|
||||
);
|
||||
$this->assertInstanceOf(
|
||||
UrlInterface::class,
|
||||
$this->getValue($api, 'apiUrl')
|
||||
);
|
||||
$this->assertInstanceOf(
|
||||
ClientInterface::class,
|
||||
$this->getValue($api, 'requestClient')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function constructPassedArgumentsDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'api key only' => ['apiKey', null, null],
|
||||
'all without client' => ['apiKey', new Url(), null],
|
||||
'all arguments' => ['apiKey', new Url(), new GuzzleClient()]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @dataProvider requestPassedDataProvider
|
||||
*
|
||||
*/
|
||||
public function testRequest($requestIsValid)
|
||||
{
|
||||
/** @var Client|MockObject apiMock */
|
||||
$apiMock = $this->getMockBuilder(Client::class)
|
||||
->onlyMethods(['rawRequest'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$apiMock->expects($this->exactly((int) $requestIsValid))->method('rawRequest');
|
||||
|
||||
/** @var ResponseInterface|MockObject $responseMock */
|
||||
$responseMock = $this->getMockBuilder(Response::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
/** @var RequestInterface|MockObject $requestMock */
|
||||
$requestMock = $this->getMockBuilder(TextRequest::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['validate', 'getResponseInstance', 'getUri', 'getMethod', 'getOptions'])
|
||||
->getMock();
|
||||
|
||||
/** @var InvalidArgumentException|MockObject $invalidArgExceptionMock */
|
||||
$invalidArgExceptionMock = $this->getMockBuilder(InvalidArgumentException::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
if ($requestIsValid) {
|
||||
$requestMock->expects($this->atLeastOnce())->method('validate')->willReturn(true);
|
||||
} else {
|
||||
$requestMock->expects($this->atLeastOnce())->method('validate')
|
||||
->willThrowException($invalidArgExceptionMock);
|
||||
}
|
||||
$requestMock->expects($this->exactly((int) $requestIsValid))
|
||||
->method('getResponseInstance')->willReturn($responseMock);
|
||||
$requestMock->expects($this->exactly((int) $requestIsValid))
|
||||
->method('getUri')->willReturn('fixtureUrl');
|
||||
$requestMock->expects($this->exactly((int) $requestIsValid))
|
||||
->method('getMethod')->willReturn(RequestInterface::METHOD_GET);
|
||||
$requestMock->expects($this->exactly((int) $requestIsValid))
|
||||
->method('getOptions')->willReturn([]);
|
||||
|
||||
$this->api = $apiMock;
|
||||
|
||||
if (false === $requestIsValid) {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
}
|
||||
|
||||
$this->assertSame(
|
||||
$responseMock,
|
||||
$this->callMethod($this->api, 'request', [$requestMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function requestPassedDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'request is valid' => [true],
|
||||
'request is not valid' => [false]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @param $useLogger
|
||||
* @param $okStatus
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @dataProvider rawRequestDataProvider
|
||||
*/
|
||||
public function testRawRequest($useLogger, $okStatus)
|
||||
{
|
||||
$statusCode = $okStatus ? '200' : '301';
|
||||
|
||||
/** @var StreamInterface|MockObject $streamMock */
|
||||
$streamMock = $this->getMockBuilder(StreamInterface::class)
|
||||
->getMock();
|
||||
|
||||
/** @var MessageResponseInterface|MockObject $responseMock */
|
||||
$responseMock = $this->getMockBuilder(MessageResponseInterface::class)
|
||||
->onlyMethods([
|
||||
'getStatusCode',
|
||||
'getBody',
|
||||
'withStatus',
|
||||
'getReasonPhrase',
|
||||
'getProtocolVersion',
|
||||
'withProtocolVersion',
|
||||
'getHeaders',
|
||||
'hasHeader',
|
||||
'getHeader',
|
||||
'getHeaderLine',
|
||||
'withHeader',
|
||||
'withAddedHeader',
|
||||
'withoutHeader',
|
||||
'withBody'
|
||||
])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$responseMock->expects($this->atLeastOnce())->method('getStatusCode')->willReturn($statusCode);
|
||||
$responseMock->expects($useLogger && $okStatus ? $this->atLeastOnce() : $this->never())
|
||||
->method('getBody')->willReturn($streamMock);
|
||||
|
||||
/** @var GuzzleClient|MockObject $requestClientMock */
|
||||
$requestClientMock = $this->getMockBuilder(GuzzleClient::class)
|
||||
->onlyMethods(['request'])
|
||||
->getMock();
|
||||
$requestClientMock->expects($this->once())->method('request')->willReturn($responseMock);
|
||||
|
||||
/** @var LoggerInterface|MockObject $loggerMock */
|
||||
$loggerMock = $this->getMockBuilder(AbstractLogger::class)
|
||||
->onlyMethods(['debug', 'error', 'log'])
|
||||
->getMock();
|
||||
|
||||
/** @var Client|MockObject $clientMock */
|
||||
$clientMock = $this->getMockBuilder(Client::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods([
|
||||
'hasLogger',
|
||||
'getLogger'
|
||||
])
|
||||
->getMock();
|
||||
$clientMock->method('hasLogger')->willReturn($useLogger);
|
||||
$clientMock->expects($useLogger ? $this->atLeastOnce() : $this->never())
|
||||
->method('getLogger')->willReturn($loggerMock);
|
||||
$this->setValue($clientMock, 'requestClient', $requestClientMock);
|
||||
|
||||
if (false === $okStatus) {
|
||||
$this->expectException(ApiException::class);
|
||||
}
|
||||
$this->assertSame(
|
||||
$responseMock,
|
||||
$this->callMethod($clientMock, 'rawRequest', ['myUrl'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rawRequestDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'has logger, OK status' => [true, true],
|
||||
'has no logger, OK status' => [false, true],
|
||||
'has logger, NOK status' => [true, false],
|
||||
'has no logger, NOK status' => [false, false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function testLogger()
|
||||
{
|
||||
$this->assertFalse($this->callMethod($this->api, 'hasLogger'));
|
||||
$this->assertNull($this->callMethod($this->api, 'getLogger'));
|
||||
|
||||
/** @var LoggerInterface|MockObject $loggerMock */
|
||||
$loggerMock = $this->getMockBuilder(AbstractLogger::class)
|
||||
->onlyMethods(['debug', 'error', 'log'])
|
||||
->getMock();
|
||||
|
||||
$this->assertSame(
|
||||
$this->api,
|
||||
$this->callMethod($this->api, 'setLogger', [$loggerMock])
|
||||
);
|
||||
|
||||
$this->assertTrue($this->callMethod($this->api, 'hasLogger'));
|
||||
$this->assertSame(
|
||||
$loggerMock,
|
||||
$this->callMethod($this->api, 'getLogger')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Installation
|
||||
|
||||
```
|
||||
composer create-project -s dev --prefer-source --repository="{\"url\": \"gitfhfac@git.d3data.de:D3Private/linkmobility-php-client.git\", \"type\": \"vcs\"}" d3/linkmobility-php-client .
|
||||
composer create-project -s dev --prefer-source d3/linkmobility-php-client .
|
||||
```
|
||||
|
||||
# Run tests
|
||||
|
63
Tests/UrlTest.php
Normal file
63
Tests/UrlTest.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This Software is the property of Data Development and is protected
|
||||
* by copyright law - it is NOT Freeware.
|
||||
* Any unauthorized use of this software without a valid license
|
||||
* is a violation of the license agreement and will be prosecuted by
|
||||
* civil and criminal law.
|
||||
* http://www.shopmodule.com
|
||||
*
|
||||
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
|
||||
* @link http://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace D3\LinkmobilityClient\Tests;
|
||||
|
||||
use D3\LinkmobilityClient\Url;
|
||||
use ReflectionException;
|
||||
|
||||
class UrlTest extends ApiTestCase
|
||||
{
|
||||
/** @var Url */
|
||||
public Url $url;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setUp():void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->url = new Url();
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
unset($this->url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function testGetBaseUri()
|
||||
{
|
||||
$fixture = "fixtureUri";
|
||||
$this->setValue($this->url, 'baseUri', $fixture);
|
||||
|
||||
$this->assertSame(
|
||||
$fixture,
|
||||
$this->callMethod(
|
||||
$this->url,
|
||||
'getBaseUri'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -20,13 +20,11 @@ namespace D3\LinkmobilityClient;
|
||||
use D3\LinkmobilityClient\Exceptions\ApiException;
|
||||
use D3\LinkmobilityClient\Exceptions\ExceptionMessages;
|
||||
use D3\LinkmobilityClient\Request\RequestInterface;
|
||||
use D3\LinkmobilityClient\ValueObject\ValueObject;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use InvalidArgumentException;
|
||||
use phpDocumentor\Reflection\Types\Mixed_;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
|
||||
class Client
|
||||
{
|
||||
@ -35,14 +33,9 @@ class Client
|
||||
public $requestClient;
|
||||
|
||||
private $logger;
|
||||
private $configuration = [];
|
||||
|
||||
public function __construct(string $accessToken, $apiUrl = false, $client = false)
|
||||
public function __construct(string $accessToken, UrlInterface $apiUrl = null, ClientInterface $client = null)
|
||||
{
|
||||
if ($apiUrl !== false && false === $apiUrl instanceof UrlInterface) {
|
||||
throw new RuntimeException(ExceptionMessages::WRONG_APIURL_INTERFACE);
|
||||
}
|
||||
|
||||
$this->accessToken = $accessToken;
|
||||
$this->apiUrl = $apiUrl ?: new Url();
|
||||
$this->requestClient = $client ?: new \GuzzleHttp\Client( [ 'base_uri' => $this->apiUrl->getBaseUri() ] );
|
||||
@ -87,7 +80,7 @@ class Client
|
||||
);
|
||||
|
||||
if ($response->getStatusCode() != 200) {
|
||||
$message = sprintf(ExceptionMessages::NOK_REQUEST_RETURN, [$url, $response->getStatusCode()]);
|
||||
$message = sprintf(ExceptionMessages::NOK_REQUEST_RETURN, $url, $response->getStatusCode());
|
||||
if ($this->hasLogger()) $this->getLogger()->error($message);
|
||||
throw new ApiException($message);
|
||||
}
|
||||
@ -123,40 +116,8 @@ class Client
|
||||
/**
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
public function getLogger(): LoggerInterface
|
||||
public function getLogger(): ?LoggerInterface
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param $configuration
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setConfiguration( string $name, $configuration ): Client
|
||||
{
|
||||
$this->configuration[$name] = oxNew(ValueObject::class, $configuration);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasConfiguration(string $name)
|
||||
{
|
||||
return isset($this->configuration[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getConfiguration(string $name)
|
||||
{
|
||||
if (false === isset($this->configuration)) {
|
||||
throw new InvalidArgumentException('configuration '.$name.' is not set');
|
||||
}
|
||||
|
||||
return $this->configuration[$name];
|
||||
return $this->hasLogger() ? $this->logger : null;
|
||||
}
|
||||
}
|
@ -19,8 +19,6 @@ class ExceptionMessages
|
||||
{
|
||||
const INVALID_SENDER = 'invalid sender phone number';
|
||||
|
||||
const WRONG_APIURL_INTERFACE = 'ApiUrl instance must implement UrlInterface';
|
||||
|
||||
const NOK_REQUEST_RETURN = 'request %1$s returns status code %2$s';
|
||||
|
||||
const INVALID_RECIPIENT_PHONE = 'invalid recipient phone number';
|
||||
|
Loading…
Reference in New Issue
Block a user