Unit Testing Guzzle inside of Laravel Controller with PHPUnit

The "classic TDD" response to this would be that you shouldn't unit test Guzzle at all. Guzzle is a third-party library which should be (and is) tested perfectly adequately by its own developer.

What you need to test is whether your code correctly calls Guzzle, not whether Guzzle works when your code calls it.

The way to do this is as follows:

Rather than doing a new Guzzle() in your controller, you should instead pass a Guzzle object into your controller using dependency injection. Fortunately, Laravel makes this very easy; all you need to do is have a constructor method for your controller class, and have a Guzzle object defined as one of its arguments. Laravel will do the rest of creating the object and passing it in for you. Your constructor can then copy it to a class property so that your other methods can use it.

Your class should now look something like this:

class Widgets extends Controller {
    private $guzzle;
    public function __construct(GuzzleHttp\Client $guzzle)
    {
        $this->guzzle = $guzzle;
    }

    public function index(){
        // Stuff

        $url = "api.example.com";

        $response = $this->guzzle->request('POST', $url, ['body' => array(...)]);

        // More stuff
    }
}

Now your test should be a lot easier to write. You can pass a mock Guzzle object into your class when you test it.

Now you can just watch your mock class to make sure that the calls to it match what the Guzzle API would expect to recieve in order to make the call.

If the rest of your class depends on the output received from Guzzle then you can define that in your mock as well.


Use https://github.com/php-vcr/php-vcr package. It helps to record and replay HTTP requests. It is very handy for testing api calls via Guzzle