Имитация ответа и одновременное использование промежуточного программного обеспечения истории в Guzzle

Есть ли способ издеваться над ответом и запросом в Guzzle?

У меня есть класс, который отправляет запрос, и я хочу его протестировать.

В Guzzle doc я нашел способ, как я могу имитировать ответ и запрос отдельно. Но как мне их совместить?

Потому что, если использовать стек истории, жрать, пытаясь отправить реальный запрос. И наоборот, когда я имитирую обработчик ответа, я не могу проверить запрос.

class MyClass {

     public function __construct($guzzleClient) {

        $this->client = $guzzleClient;

    }

    public function registerUser($name, $lang)
    {

           $body = ['name' => $name, 'lang' = $lang, 'state' => 'online'];

           $response = $this->sendRequest('PUT', '/users', ['body' => $body];

           return $response->getStatusCode() == 201;        
    }

   protected function sendRequest($method, $resource, array $options = [])
   {

       try {
           $response = $this->client->request($method, $resource, $options);
       } catch (BadResponseException $e) {
           $response = $e->getResponse();
       }

       $this->response = $response;

      return $response;
  }

}

Тест:

class MyClassTest {

  //....
 public function testRegisterUser()

 { 

    $guzzleMock = new \GuzzleHttp\Handler\MockHandler([
        new \GuzzleHttp\Psr7\Response(201, [], 'user created response'),
    ]);

    $guzzleClient = new \GuzzleHttp\Client(['handler' => $guzzleMock]);

    $myClass = new MyClass($guzzleClient);
    /**
    * But how can I check that request contains all fields that I put in the body? Or if I add some extra header?
    */
    $this->assertTrue($myClass->registerUser('John Doe', 'en'));


 }
 //...

}

person xAoc    schedule 09.02.2017    source источник
comment
Разместите код. Описание довольно запутанное. Какой смысл издеваться над запросами? Вы тестируете пользовательские обработчики?   -  person Alex Blex    schedule 09.02.2017
comment
Я обновил код @AlexBlex. На примере фиктивного ответа и в документе мы можем узнать, как проверить запрос. Вопрос, как я могу смешать это docs.guzzlephp.org/en/latest /testing.html#mock-handler и эти документы. guzzlephp.org/en/latest/testing.html#history-middleware   -  person xAoc    schedule 10.02.2017
comment
$response = $this->sendRequest('PUT', '/users', ['body' => $body]; Нет завершающей скобки. И 'lang' = 'ru' должно быть 'lang' => 'ru'   -  person matchish    schedule 07.03.2019


Ответы (2)


@Alex Blex был очень близок.

Решение:

$container = [];
$history = \GuzzleHttp\Middleware::history($container);

$guzzleMock = new \GuzzleHttp\Handler\MockHandler([
    new \GuzzleHttp\Psr7\Response(201, [], 'user created response'),
]);

$stack = \GuzzleHttp\HandlerStack::create($guzzleMock);

$stack->push($history);

$guzzleClient = new \GuzzleHttp\Client(['handler' => $stack]);
person xAoc    schedule 10.02.2017
comment
Спасибо, это избавило меня от многих головных болей. - person DonCallisto; 11.12.2019

Во-первых, вы не издеваетесь над запросами. Запросы — это настоящие запросы, которые вы собираетесь использовать в производстве. Мок-обработчик на самом деле представляет собой стек, поэтому вы можете поместить туда несколько обработчиков:

$container = [];
$history = \GuzzleHttp\Middleware::history($container);

$stack = \GuzzleHttp\Handler\MockHandler::createWithMiddleware([
    new \GuzzleHttp\Psr7\Response(201, [], 'user created response'),
]);

$stack->push($history);

$guzzleClient = new \GuzzleHttp\Client(['handler' => $stack]);

После того, как вы запустите свои тесты, $container будет иметь все транзакции для подтверждения. В вашем конкретном тесте - одна транзакция. Вас интересует $container[0]['request'], так как $container[0]['response'] будет содержать ваш готовый ответ, так что на самом деле утверждать нечего.

person Alex Blex    schedule 10.02.2017
comment
Я получил сообщение об ошибке [ErrorException] Аргумент 1, переданный в GuzzleHttp\Handler\MockHandler::__invoke(), должен реализовать интерфейс Psr\Http\Message\RequestInterface, данный экземпляр Closure вызывается в /vendor/guzzlehttp/guzzle/src/HandlerStack. php в строке 199 и определено - person xAoc; 10.02.2017
comment
Ах, извините, забыл, что MockHandler должен использовать фабрику для создания стека. Я обновил ответ. - person Alex Blex; 10.02.2017