phpunit-testingguzzlephpspec

Testing a class in phpspec involving Guzzle


I'm trying to build a class that queries an external API. Each method that corresponds to an endpoint makes a call to a 'master call' method responsible for actually sending a request to the API.

For example:

// $this->http is Guzzlehttp\Client 5.3

public function call($httpMethod, $endpoint, array $parameters = [])
{
    $parameters = array_merge($parameters, [
        'headers' => [
            'something' => 'something'
        ]
    ]);

    $request = $this->http->createRequest($httpMethod, $this->baseUrl . $endpoint, $parameters);

    return $this->http->send($request);
}

public function getAll()
{
    return $this->call('GET', 'all');
}

What I'm I supposed to mock? Should I use willBeCalled() and/or willReturn() on the http client's createRequest() and send() methods?

When I mock send(), it says: Argument 1 passed to Double\GuzzleHttp\Client\P2::send() must implement interface GuzzleHttp\Message\RequestInterface, null given and I'm not sure how to provide a fake for that, because creating a dummy for that interface requires me to implement 30 methods on that class.

Here's the test right now:

function it_lists_all_the_things(HttpClient $http)
{
    $this->call('GET', 'all')->willBeCalled();
    $http->createRequest()->willBeCalled();
    $http->send()->willReturn(['foo' => 'bar']);

    $this->getAll()->shouldHaveKeyWithValue('foo', 'bar'); 
}

Solution

  • You should mock the behaviour, something like this:

    public function let(Client $http)
    {
        $this->beConstructedWith($http, 'http://someurl.com/');
    }
    
    function it_calls_api_correctly(Client $http, Request $request)
    {
        $parameters = array_merge([
            'headers' => [
                'something' => 'something'
            ]
        ]);
    
        $http->createRequest('GET', 'http://someurl.com/all', $parameters)->shouldBeCalled()->willReturn($request);
    
        $http->send($request)->shouldBeCalled();
    
        $this->getAll();
    }