I’m trying to 100% code coverage my service. Here is a method:
<?php
* Search to public accounts.
*
* @param string $query
*
* @return TwitterResponse
*/
public function search(string $query): TwitterResponse
{
try {
$response = $this->client->getClient()->get(UserEnum::URI_SEARCH, [
'query' => ['q' => $query,]
]);
} catch (ClientException $e) {
$response = $e->getResponse();
}
return new TwitterResponse($response);
}
It simply GET a user with Twitter API.
In my opinion, I should develop two tests : one for the try and one for the catch. Bellow is my test for the try.
<?php
/**
* @return void
*/
public function setUp(): void
{
$this->prophet = new Prophet();
$this->client = $this->prophet->prophesize(Client::class);
$this->client->get(Argument::any(), Argument::any())->willReturn(new TwitterResponse(new Response()));
$this->client->post(Argument::any(), Argument::any())->willReturn(new TwitterResponse(new Response()));
$this->twitterClient = $this->prophet->prophesize(TwitterClient::class);
$this->twitterClient->getClient()->willReturn($this->client);
$this->userService = new UserService($this->twitterClient->reveal());
}
/**
* Tests if a TwitterResponse is returned with status HTTP_OK.
*
* @return void
*/
public function testGetOk(): void
{
$actual = $this->userService->get('');
$this->assertEquals(get_class($actual), TwitterResponse::class);
$this->assertEquals(HttpResponse::HTTP_OK, $actual->getStatusCode());
}
Bellow the code coverage of get().
As you can see, I don’t test the catch case. How can I do it ? I already tried to mock a 404 HTTP response catch something but it did not work. Do you have an idea of how I can do it ?
Thanks.
EDIT : I tried this for the catch case ->
public function testGetKo(): void
{
$response = new TwitterResponse(new Response(HttpResponse::HTTP_NOT_FOUND));
$response->setStatusCode(HttpResponse::HTTP_NOT_FOUND);
$this->client = $this->prophet->prophesize(Client::class);
$this->client->get(Argument::any(), Argument::any())->willReturn($response);
$this->twitterClient = $this->prophet->prophesize(TwitterClient::class);
$actual = $this->userService->get('');
$this->assertEquals(get_class($actual), TwitterResponse::class);
$this->assertEquals(HttpResponse::HTTP_NOT_FOUND, $actual->getStatusCode());
}
Phpunit returns : Failed asserting that 200 matches expected 404. It seems that my mock client doesn’t work well.
2
Answers
This is untested, as I don’t usually use prophecy, but I do simialry with other mocking frameworks:
And you will likely add
$this->expectException(ClientException::class);
before you run the function being tested.I know, it’s an old post, but..
Maybe try to mock client, and when it’s triggered throw exception?
So when you throw ClientException, you should check for TwitterResponse result. And when you throw DummyException, you should expect DummyException.