【问题标题】:How to unit test this try catch如何对这个 try catch 进行单元测试
【发布时间】:2018-10-29 06:19:03
【问题描述】:

我正在尝试 100% 的代码覆盖我的服务。这是一个方法:

<?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);
}

它只是通过 Twitter API 获取用户。

在我看来,我应该开发两种测试:一种用于尝试,另一种用于捕获。 Bellow 是我的尝试。

<?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());
}

下面是 get() 的代码覆盖率。

如您所见,我没有测试 catch 案例。我该怎么做 ?我已经尝试模拟 404 HTTP 响应捕获某些东西,但它不起作用。你知道我该怎么做吗?

谢谢。

编辑:我为 catch 案例尝试了这个 ->

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 返回:断言 200 匹配预期的 404 失败。 看来我的模拟客户端运行不正常。

【问题讨论】:

  • 弄清楚究竟是什么导致了ClientException。创建一个满足该异常的客户端。
  • 我已经尝试过这个解决方案;)遇到客户端错误(4xx 代码)时会捕获 ClientException。我将编辑我的第一篇文章以展示我尝试过的内容。
  • 创建一个存根或模拟到getClient(),它会抛出一个ClientException
  • 我试过这个:$this-&gt;client-&gt;get(Argument::any(), Argument::any()-&gt;willReturn(new ClientException('', new Request('GET', ''))); 但我仍然有同样的信息。

标签: php phpunit try-catch code-coverage


【解决方案1】:

我知道,这是一篇旧帖子,但是..

也许尝试模拟客户端,什么时候触发抛出异常?

因此,当您抛出 ClientException 时,您应该检查 TwitterResponse 结果。当你抛出 DummyException 时,你应该期待 DummyException。

【讨论】:

    【解决方案2】:

    这是未经测试的,因为我通常不使用预言,但我与其他模拟框架类似:

    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);
    

    您可能会在运行正在测试的函数之前添加$this-&gt;expectException(ClientException::class);

    【讨论】:

    • 你好,它不起作用,因为我的方法总是返回一个 TwitterReponse,即使我去 catch() 案例。那么来自 guzzle 的 GET 将永远不会抛出 ClientException。
    猜你喜欢
    • 2013-12-19
    • 1970-01-01
    • 2020-06-08
    • 1970-01-01
    • 2022-11-12
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多