Я пытаюсь издеваться над жадным ответом от определенного API.
Код моего контроллера выглядит так (исправлено для краткости):
class SomeClass
{
private $guzzle;
public function __construct(\GuzzleHttp\Client $guzzle) {
$this->guzzle = new $guzzle();
}
public function makeRequest(){
$client = $this->guzzle;
$url = 'http//somerurl';
$options = [];
$response = $client->request('POST', $url, $options);
return $response;
}
}
А тест выглядит примерно так (опять же отредактировано)...
public function someTest(){
$mock = $this->createMock(\GuzzleHttp\Client::class);
$mock->method('request')->willReturn([
'response' => 'somedata'
]);
$someClass = new $SomeClass($mock);
$response = $someClass->makeRequest();
$body = $response->getBody();
...
}
В этот момент тест возвращает «Вызов функции-члена getBody при нулевом значении»;
Как можно протестировать ответ getBody на вызов guzzle?
Заранее спасибо...





Один из подходов к тестированию с помощью Guzzle — настроить MockHandler
http://docs.guzzlephp.org/en/stable/testing.html
Таким образом, вместо того, чтобы издеваться над клиентом guzzle, вы создаете его следующим образом:
public function someTest() {
$mock = new MockHandler([
new Response(200, [], 'The body!'),
// Add more responses for each response you need
]);
$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);
$someClass = new SomeClass($client);
$response = $someClass->makeRequest();
$body = $response->getBody();
$this->assertSame('The body!', $body);
}
Код живет в тесте. Вы создаете ответ вместо того, чтобы издеваться над ним. Если вы хотите использовать phpunit для имитации, вам нужно вместо этого использовать $mock->method('request')->willReturn(new Response(200, [], 'hello'));.
Это не работает. Точно такая же ошибка, как и раньше.
MockHandler требует, чтобы вы «ставили в очередь» ответы, то есть вам нужно знать, в каком порядке будут выполняться внешние вызовы API. Я сделал еще один шаг вперед и обернул MockHandler другим обработчиком, способным вставить в него фиктивный ответ в последний момент, если он еще не ждет своего часа. См. https://gist.github.com/kmuenkel/d4d473beb7b2297ac2d8cd480089a738
Просто используйте эту черту в своем тесте и вызовите $this->mockGuzzleResponses(); из метода setUp() тестового класса. В этот момент все запросы, предназначенные для прохождения через Guzzle, будут доступны для утверждений с помощью свойства $guzzleRequestLog, а все ответы могу будут имитированы путем вызова $this->guzzleHandler->append(RequestInterface); в начале вашего теста.
Просто убедитесь, что все реализации Guzzle в вашем коде созданы с помощью помощника app(Client::class) и нетnew Client. В противном случае переопределение привязки не вступит в силу. Возможно, это была ваша проблема раньше.
Взгляните на мой пакет композитора https://packagist.org/packages/doppiogancio/mocked-client.
На мой взгляд, это очень простой способ смоделировать клиент Guzzle, привязав URL-адреса запросов к ответам.
$builder = new HandlerStackBuilder();
// Add a route with a response via callback
$builder->addRoute(
'GET', '/country/IT', static function (ServerRequestInterface $request): Response {
return new Response(200, [], '{"id":"+39","code":"IT","name":"Italy"}');
}
);
// Add a route with a response in a text file
$builder->addRouteWithFile('GET', '/country/IT/json', __DIR__ . '/fixtures/country.json');
// Add a route with a response in a string
$builder->addRouteWithString('GET', '/country/IT', '{"id":"+39","code":"IT","name":"Italy"}');
// Add a route mocking directly the response
$builder->addRouteWithResponse('GET', '/admin/dashboard', new Response(401));
$client = new Client(['handler' => $builder->build()]);
Как только вы это сделаете, у вас будет полнофункциональный клиент для обычного использования.
$response = $client->request('GET', '/country/DE/json');
$body = (string) $response->getBody();
$country = json_decode($body, true);
print_r($country);
// will return
Array
(
[id] => +49
[code] => DE
[name] => Germany
)
И что потом? Куда идет этот код? Как это согласуется с тем, чего я пытаюсь добиться в написанном мной коде?