在Guzzle中同时使用模拟响应和历史记录中间件

7

有没有办法在Guzzle中模拟响应和请求?

我有一个类发送一些请求,我想要测试。

在Guzzle doc 中,我找到了一种分别模拟响应和请求的方法。但是如何将它们组合起来呢?

因为,如果使用历史记录堆栈,Guzzle会尝试发送真实请求。反之亦然,当我模拟响应处理程序时,无法测试请求。


其中,link1需要翻译成对应的链接文字。
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'));


 }
 //...

}

发布一些代码。描述相当混乱。模拟请求的目的是什么?你是在测试自定义处理程序吗? - Alex Blex
我已经更新了代码@AlexBlex。提供了一个模拟响应的示例,并在文档中说明了如何检查请求。问题是,我该如何将这个http://docs.guzzlephp.org/en/latest/testing.html#mock-handler和这个http://docs.guzzlephp.org/en/latest/testing.html#history-middleware混合使用? - xAoc
$response = $this->sendRequest('PUT', '/users', ['body' => $body]; No trailing bracket.
And 'lang' = 'ru' should be 'lang' => 'ru'
- Serhii Shliakhov
2个回答

12

@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]);

谢谢,这节省了我很多麻烦。 - DonCallisto

2

首先,您不应嘲笑请求。这些请求是您将在生产中使用的真实请求。模拟处理程序实际上是一个堆栈,因此您可以将多个处理程序推送到其中:

$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'] 将包含您的预设响应,所以实际上没有什么可以断言的。


我收到了一个错误 [ErrorException]:传递给GuzzleHttp \ Handler \ MockHandler :: __ invoke()的第1个参数必须实现接口Psr \ Http \ Message \ RequestInterface,但给定了Closure实例,在/ vendor / guzzlehttp / guzzle / src / HandlerStack.php的第199行调用并定义 - xAoc
啊,抱歉,我忘记了MockHandler应该使用工厂来创建堆栈。我已经更新了答案。 - Alex Blex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接