Reputation: 6081
I'm using Guzzle's asynchronous request and have them implemented in a service that I would like to test now.
My method looks like this (pseudo, so if it's not 100% valid, please excuse)
public function getPlayer(string $uiid, array &$player = [])
{
$options['query'] = ['id' => $uiid];
$promise = $this->requestAsync('GET', $this->endpoint, $options);
$promise->then(function (ResponseInterface $response) use (&$player) {
$player = $response->getBody()->getContents();
});
return $players;
}
Now I want to test it, but I don't really know how to mock the callable, because I'm always getting the error
1) tzfrs\PlayerBundle\Tests\Api\Player\PlayerServiceTest::testGetPlayer
Prophecy\Exception\InvalidArgumentException: Expected callable or instance of PromiseInterface, but got object.
This is how I have it implemented currently
/** @var ObjectProphecy|PromiseInterface $response */
$promise = $this->prophesize(PromiseInterface::class);
$promise->then()->will($this->returnCallback(function (ResponseInterface $response) use (&$player){}));
Didn't work. And this
$this->returnCallback(function (ResponseInterface $response) use (&$player){})
didn't work either. Same error. And when simply trying a dummy callback
$promise->then(function(){});
I get the error Error: Call to a member function then() on string
, even after ->reveal()
ing the promise first. Any ideas?
Upvotes: 0
Views: 6763
Reputation: 3051
I had another idea.
Make a dependency that will make what you make now in requestAsync()
;
And then create it's mock that will return another mock of promise.
class PromiseMock
{
private $response;
public function __construct(ResponseInterface $response)
{
$this->response = $response;
}
public function then($callable)
{
$callable($this->response);
}
}
test looks like
public function testGetPlayer()
{
$response = new Response(200, [], "Your test response");
$promiseMock = new PromiseMock($response);
$mockDependency = $this->getMockBuilder('YourDependencyClass')
->getMock()
->expects("requestAsync")->willReturn($promiseMock);
$service = new YouServiceClass($mockDependency);
$service->getPlayer("76245914-d56d-4bac-8419-9e409f43e777");
}
And in your class changes only
$promise = $this->someNameService->requestAsync('GET', $this->endpoint, $options);
Upvotes: 2
Reputation: 3051
I would inject a processor to your class and call it's callable. Check it out, the rest is quite obvious:
public function __construct(Processor $processor) {
$this->processor = $processor;
}
public function getPlayer(string $uiid, array &$player = [])
{
$options['query'] = ['id' => $uiid];
$promise = $this->requestAsync('GET', $this->endpoint, $options);
$promise->then([$this->processor, "processResponse"]);
$player = $this->processor->getPlayer();
return $players;
}
And processor:
class Processor {
private $player;
public function processResponse (ResponseInterface $response) {
$this->player = $response->getBody()->getContents();
}
public function getPlayer() { return $this->player;}
}
Upvotes: 1