Issue
I am using Cake\Http\Client
(book) to access some external applications. In my unit tests I cannot actually use those services.
So how to mock the Http Client in a controller integration test? It would be nice if I could for instance prescribe the exact response, without it ever making the actual HTTP request.
In my case the requests are made in a controller action and the destination is some other application on the same server. However, I feel like a solution to this should independent of the HTTP target.
Solution
I'm pretty certain there is no built-in solution to mocking the Http\Client object, considering I can't find anything in the docs or api pages.
So instead I used another PHP HTTP client, Guzzle. Guzzle does allow mocking by queuing pre-defined responses, exactly what I wanted.
However, smooth integration with CakePHP was not trivial since the Guzzle client constructor requires the mock stack to be passed. I solved this by creating a client factory:
<?php
namespace App\Guzzle;
use GuzzleHttp\Client;
/**
* Guzzle factory
*
* Created to make guzzle clients mockable
*/
class GuzzleFactory
{
static $options = [];
/**
* Create new client
*
* @return \GuzzleHttp\Client
*/
static function create()
{
return new Client(self::$options);
}
/**
* Set handler stack in global options for new clients
*
* @param \GuzzleHttp\HandlerStack $handlerStack
*/
static function setTest($handlerStack)
{
self::$options['handler'] = $handlerStack;
}
/**
* Set options array to default
*/
static function reset()
{
self::$options = [];
}
}
Then in my controller tests I have the function:
/**
* Set Guzzle mock responses
*
* @param array $list
*/
public function setGuzzleResponses($list)
{
if (!is_array($list))
{
$list = [$list];
}
$mock = new MockHandler($list);
$handlerStack = HandlerStack::create($mock);
GuzzleFactory::setTest($handlerStack);
}
Such that inside a test I can call:
// ...
$this->setGuzzleResponses([
new Response(200, [], json_encode($response))
]);
$this->get("/page/index"); // This request will make an HTTP call
// ...
Also see http://docs.guzzlephp.org/en/stable/testing.html
Answered By - Roberto
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.