mirror of
https://github.com/Neur0toxine/pock.git
synced 2024-12-01 01:16:07 +03:00
fix for the array serialization, more tests and initial readme, and... you know now where I found an example for the phpDocumentor config
This commit is contained in:
parent
38df010cf9
commit
4a7030f7c2
105
README.md
105
README.md
@ -5,8 +5,107 @@
|
||||
|
||||
# pock
|
||||
|
||||
Easy to use HTTP mocking solution, compatible with PSR-18 and HTTPlug. Should resemble [gock](https://github.com/h2non/gock) in the end.
|
||||
Easy to use HTTP mocking solution, compatible with PSR-18 and HTTPlug.
|
||||
|
||||
Project in its early development stage. User manual is not there yet, but you can find autogenerated documentation [here](neur0toxine.github.io/pock/).
|
||||
Project is still in its early development stage. API can change over time, but I'll try to not introduce breaking changes.
|
||||
You can find autogenerated documentation [here](neur0toxine.github.io/pock/) or look at the examples.
|
||||
|
||||
Most of the desired functionality is already implemented, but the API itself can change over time.
|
||||
# Examples
|
||||
|
||||
Mock JSON API route with Basic authorization, reply with JSON.
|
||||
|
||||
```php
|
||||
use Pock\Enum\RequestMethod;
|
||||
use Pock\Enum\RequestScheme;
|
||||
use Pock\PockBuilder;
|
||||
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost('example.com')
|
||||
->matchPath('/api/v1/users')
|
||||
->matchHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Basic YWxhZGRpbjpvcGVuc2VzYW1l'
|
||||
])
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withJson([
|
||||
[
|
||||
'name' => 'John Doe',
|
||||
'username' => 'john',
|
||||
'email' => 'john@example.com'
|
||||
],
|
||||
[
|
||||
'name' => 'Jane Doe',
|
||||
'username' => 'jane',
|
||||
'email' => 'jane@example.com'
|
||||
],
|
||||
]);
|
||||
|
||||
// Pass PSR-18 compatible client to the API client.
|
||||
$client = new MysteriousApiClient($builder->getClient());
|
||||
$client->setCredentials('username', 'password');
|
||||
|
||||
// Receive mock response.
|
||||
$response = $client->getUsers();
|
||||
```
|
||||
|
||||
Same mock, but with models! Also, the code itself is slightly shorter.
|
||||
|
||||
```php
|
||||
use Pock\Enum\RequestMethod;
|
||||
use Pock\PockBuilder;
|
||||
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchUri('https://example.com/api/v1/users')
|
||||
->matchHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Basic YWxhZGRpbjpvcGVuc2VzYW1l'
|
||||
])
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withJson([
|
||||
// We're assuming here that MysteriousUser's constructor can receive an initial values.
|
||||
new MysteriousUser('John Doe', 'john', 'john@example.com'),
|
||||
new MysteriousUser('Jane Doe', 'jane', 'jane@example.com'),
|
||||
]);
|
||||
|
||||
// Pass PSR-18 compatible client to the API client.
|
||||
$client = new MysteriousApiClient($builder->getClient());
|
||||
$client->setCredentials('username', 'password');
|
||||
|
||||
// Receive mock response.
|
||||
$response = $client->getUsers();
|
||||
```
|
||||
|
||||
It is possible to mock a response using DTO's because pock can use third-party serializers under the hood.
|
||||
|
||||
# Serializer support
|
||||
|
||||
pock supports JMS serializer and Symfony serializer out of the box. Available serializer will be instantiated automatically.
|
||||
It will be used to serialize requests and responses in mocks which means you actually can pass an entire DTO
|
||||
into the corresponding methods (for example, `matchJsonBody` as an assertion or `withJsonBody` to generate a response body).
|
||||
|
||||
By default JMS serializer has more priority than the Symfony serializer. You can use methods below before running tests (`bootstrap.php`)
|
||||
if you want to override default behavior.
|
||||
|
||||
```php
|
||||
use Pock\Factory\JsonSerializerFactory;
|
||||
use Pock\Factory\XmlSerializerFactory;
|
||||
use Pock\Serializer\SymfonySerializerDecorator;
|
||||
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
||||
use Symfony\Component\Serializer\Encoder\XmlEncoder;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
$encoders = [new XmlEncoder(), new JsonEncoder()];
|
||||
$normalizers = [new ObjectNormalizer()];
|
||||
$serializer = new SymfonySerializerDecorator(new Serializer($normalizers, $encoders));
|
||||
|
||||
JsonSerializerFactory::setSerializer($serializer);
|
||||
XmlSerializerFactory::setSerializer($serializer);
|
||||
```
|
||||
|
||||
In order to use unsupported serializer you should create a decorator which implements `Pock\Serializer\SerializerInterface`.
|
||||
|
@ -5,7 +5,7 @@
|
||||
xmlns="https://www.phpdoc.org"
|
||||
xsi:noNamespaceSchemaLocation="https://docs.phpdoc.org/latest/phpdoc.xsd"
|
||||
>
|
||||
<title>RetailCRM API Client</title>
|
||||
<title>pock</title>
|
||||
<paths>
|
||||
<output>docs/build/html</output>
|
||||
<cache>docs/build/cache</cache>
|
||||
|
@ -13,6 +13,7 @@ use JsonSerializable;
|
||||
use Pock\Exception\JsonException;
|
||||
use Pock\Factory\JsonSerializerFactory;
|
||||
use Pock\Serializer\SerializerInterface;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Trait JsonSerializerAwareTrait
|
||||
@ -43,7 +44,11 @@ trait JsonSerializerAwareTrait
|
||||
}
|
||||
|
||||
if (is_array($data)) {
|
||||
return static::jsonEncode($data);
|
||||
try {
|
||||
return static::jsonSerializer()->serialize($data);
|
||||
} catch (Throwable $throwable) {
|
||||
return static::jsonEncode($data);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_object($data)) {
|
||||
|
@ -15,6 +15,7 @@ use Pock\Exception\UniversalMockException;
|
||||
use Pock\Exception\UnsupportedRequestException;
|
||||
use Pock\PockBuilder;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
use Pock\TestUtils\SimpleObject;
|
||||
use Psr\Http\Client\ClientExceptionInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use RuntimeException;
|
||||
@ -244,6 +245,31 @@ class PockBuilderTest extends PockTestCase
|
||||
self::assertEquals(['error' => 'Forbidden'], json_decode($response->getBody()->getContents(), true));
|
||||
}
|
||||
|
||||
public function testJsonObjectArrayResponse(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->reply(403)
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withJson([
|
||||
new SimpleObject(),
|
||||
new SimpleObject()
|
||||
]);
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
);
|
||||
|
||||
self::assertEquals(403, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['application/json']], $response->getHeaders());
|
||||
self::assertEquals([
|
||||
['field' => 'test'],
|
||||
['field' => 'test']
|
||||
], json_decode($response->getBody()->getContents(), true));
|
||||
}
|
||||
|
||||
public function testXmlResponse(): void
|
||||
{
|
||||
$xml = <<<'EOF'
|
||||
@ -272,6 +298,82 @@ EOF;
|
||||
self::assertEquals($xml, $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testFirstExampleApiMock(): void
|
||||
{
|
||||
$data = [
|
||||
[
|
||||
'name' => 'John Doe',
|
||||
'username' => 'john',
|
||||
'email' => 'john@example.com'
|
||||
],
|
||||
[
|
||||
'name' => 'Jane Doe',
|
||||
'username' => 'jane',
|
||||
'email' => 'jane@example.com'
|
||||
],
|
||||
];
|
||||
$builder = new PockBuilder();
|
||||
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost('example.com')
|
||||
->matchPath('/api/v1/users')
|
||||
->matchHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Basic YWxhZGRpbjpvcGVuc2VzYW1l'
|
||||
])
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withJson($data);
|
||||
|
||||
$request = self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, 'https://example.com/api/v1/users')
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withHeader('Authorization', 'Basic YWxhZGRpbjpvcGVuc2VzYW1l');
|
||||
$response = $builder->getClient()->sendRequest($request);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
self::assertEquals('application/json', $response->getHeaderLine('Content-Type'));
|
||||
self::assertEquals(json_encode($data), $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testSecondExampleApiMock(): void
|
||||
{
|
||||
$data = [
|
||||
[
|
||||
'name' => 'John Doe',
|
||||
'username' => 'john',
|
||||
'email' => 'john@example.com'
|
||||
],
|
||||
[
|
||||
'name' => 'Jane Doe',
|
||||
'username' => 'jane',
|
||||
'email' => 'jane@example.com'
|
||||
],
|
||||
];
|
||||
$builder = new PockBuilder();
|
||||
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchUri('https://example.com/api/v1/users')
|
||||
->matchHeaders([
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Basic YWxhZGRpbjpvcGVuc2VzYW1l'
|
||||
])
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withJson($data);
|
||||
|
||||
$request = self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, 'https://example.com/api/v1/users')
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withHeader('Authorization', 'Basic YWxhZGRpbjpvcGVuc2VzYW1l');
|
||||
$response = $builder->getClient()->sendRequest($request);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
self::assertEquals('application/json', $response->getHeaderLine('Content-Type'));
|
||||
self::assertEquals(json_encode($data), $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testSeveralMocks(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
|
Loading…
Reference in New Issue
Block a user