skip to Main Content

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().

Code coverage

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


  1. This is untested, as I don’t usually use prophecy, but I do simialry with other mocking frameworks:

    public function testGetKo(): void
    {
        // ... other setup
    
        $exception = new ClientException();
        $this->client = $this->prophet->prophesize(Client::class);
        $this->client->get(Argument::any(), Argument::any())->willThrow($exception);
    

    And you will likely add $this->expectException(ClientException::class); before you run the function being tested.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search