【问题标题】:PHPUnit and mock request from Guzzle来自 Guzzle 的 PHPUnit 和模拟请求
【发布时间】:2018-08-07 08:32:59
【问题描述】:

我有一个具有以下功能的课程:

public function get(string $uri) : stdClass
{
    $this->client = new Client;
    $response = $this->client->request(
        'GET',
        $uri,
        $this->headers
    );

    return json_decode($response->getBody());
}

如何模拟来自 PHPUnit 的请求方法?我尝试了不同的方法,但它总是尝试连接到指定的 uri。

我试过了:

    $clientMock = $this->getMockBuilder('GuzzleHttp\Client')
        ->setMethods('request')
        ->getMock();

    $clientMock->expects($this->once())
        ->method('request')
        ->willReturn('{}');

但这没有用。我能做些什么?我只需要将响应模拟为空。

谢谢

PD : 客户端来自(使用 GuzzleHttp\Client)

【问题讨论】:

  • $this->client 是如何初始化的,你是如何通过模拟的?
  • 你不需要返回一个实现 ResponseInterface 的对象而不是一个字符串吗?否则当你调用getBody时它会爆炸。
  • 当然,你的模拟应该返回一个ResponseInterface 存根,这样getBody 才能工作(你也必须模拟这个)
  • 另外docs.guzzlephp.org/en/stable/testing.html 可能比 PHPUnit 模拟更好
  • 我想用phpunit mocks

标签: php laravel mocking phpunit guzzle


【解决方案1】:

我认为建议最好使用http://docs.guzzlephp.org/en/stable/testing.html#mock-handler

因为它看起来是正确执行此操作的最优雅方式。

谢谢大家

【讨论】:

  • Guzzle 6 的 URL(固定和基于正则表达式)模拟处理程序 - tarampampam/guzzle-url-mock
  • 这是最好的方法吗?我看不到验证您是否向 guzzle 客户端发送正确参数的方法,只是模拟响应。
【解决方案2】:

模拟的响应不需要特别是任何东西,您的代码只希望它是一个具有getBody 方法的对象。因此,您可以只使用stdClassgetBody 方法,该方法返回一些json_encoded 对象。比如:

$jsonObject = json_encode(['foo']);
$uri = 'path/to/foo/bar/';

$mockResponse = $this->getMockBuilder(\stdClass::class)->getMock();

$mockResponse->method('getBody')->willReturn($jsonObject);

$clientMock = $this->getMockBuilder('GuzzleHttp\Client')->getMock();

$clientMock->expects($this->once())
    ->method('request')
    ->with(
        'GET', 
        $uri,
        $this->anything()
    )
    ->willReturn($mockResponse);

$result = $yourClass->get($uri);

$expected = json_decode($jsonObject);

$this->assertSame($expected, $result);

【讨论】:

    【解决方案3】:

    我更喜欢这种方式来模拟 PHP 中的客户端。在此示例中,我使用的是 Guzzle 客户端。

    克隆代码或通过 composer 安装

    $ composer require doppiogancio/mocked-client
    

    然后……

    $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->addRouteWithFile('GET',  '{"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
    )
    

    【讨论】:

      猜你喜欢
      • 2018-10-12
      • 2016-10-06
      • 2018-03-03
      • 2020-04-22
      • 1970-01-01
      • 2018-05-29
      • 2017-10-05
      • 2016-12-17
      • 1970-01-01
      相关资源
      最近更新 更多