How to mock the Symfony HttpClient
Hello, I will show you how we can mock the Symfony HttpClient.
Firstly we need to make a class which will collect all the needed information for our class.
<?php
namespace App\Component\Stateta;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class Collector
{
public function __construct(
private readonly HttpClientInterface $client
) {
}
/**
* @return Price[]|array
*
* @throws ClientExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
* @throws \Exception
*/
public function collect(): array
{
$prices = [];
$response = $this->client->request(
'GET',
$_ENV['STATETA_URL']
);
if (Response::HTTP_OK !== $response->getStatusCode()) {
return $prices;
}
$matches = [];
preg_match('/ProtocolData\ =(.*);/', $response->getContent(), $matches);
if (0 === \count($matches)) {
return $prices;
}
$statetaPrices = json_decode($matches[1], true);
if (\count($matches) > 0) {
$a95 = $statetaPrices[1];
$dk = $statetaPrices[0];
if ('A95' === $a95['key'] && 'DK' === $dk['key']) {
foreach ($a95['values'] as $index => $priceA95) {
$price = new Price();
$price->setDate(new \DateTimeImmutable($priceA95['date']));
$price->setA95($priceA95['y']);
$price->setDk($dk['values'][$index]['y']);
$prices[] = $price;
}
}
}
return $prices;
}
}
Secondly, we put a new test class for testing our mocked data.
<?php
namespace App\Tests\Component\Stateta;
use App\Component\Stateta\Collector;
use App\Component\Stateta\Price;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
class CollectorTest extends TestCase
{
/**
* @dataProvider dataProviderCollect
*/
public function testCollect(array $expected, array $provided)
{
$response = new MockResponse(
[
$provided['response'],
],
[
'http_code' => $provided['status_code'],
],
);
$client = new MockHttpClient($response);
$collector = new Collector($client);
self::assertEquals($expected, $collector->collect());
}
private function dataProviderCollect(): array
{
$price = new Price();
$price->setA95('1.39');
$price->setDk('1.227');
$price->setDate(new \DateTimeImmutable('2023-06-10'));
$price2 = new Price();
$price2->setA95('1.39');
$price2->setDk('1.227');
$price2->setDate(new \DateTimeImmutable('2023-06-11'));
$expected2 = [
$price,
$price2,
];
$response = <<< RESPONSE
<script type="text/javascript">
var ProtocolData = [{"key":"DK","values":[{"x":1686344400000,"y":"1.227","date":"2023-06-10"},{"x":1686430800000,"y":"1.227","date":"2023-06-11"}]},{"key":"A95","values":[{"x":1686344400000,"y":"1.390","date":"2023-06-10"},{"x":1686430800000,"y":"1.390","date":"2023-06-11"}]}];
</script>
RESPONSE;
return [
[
[],
[
'status_code' => 200,
'response' => 'OK',
],
],
[
$expected2,
[
'status_code' => 200,
'response' => $response,
],
],
[
[],
[
'status_code' => 500,
'response' => 'ERROR',
],
],
];
}
}