【问题标题】:Test and Mock by Using PHP Anonymous Class使用 PHP 匿名类进行测试和模拟
【发布时间】:2021-05-22 23:33:14
【问题描述】:

我正在尝试使用匿名类测试和模拟一段代码。这是代码:

<?php

namespace App\Service;

use Symfony\Contracts\HttpClient\HttpClientInterface;

class FetchPromoCodeService
{
    private $client;

    public function __construct(HttpClientInterface $client)
    {
        $this->client = $client;
    }

    public function getPromoCodeList(): array
    {
        $response = $this->client->request(
            'GET', 'https://xxxxxxxxx.mockapi.io/test/list'
        );

        return $response->toArray();
    }
}

这是我的测试类:

<?php

namespace App\Tests\Service;

use App\Service\FetchPromoCodeService;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\JsonResponse;

class FetchPromoCodeServiceTest extends TestCase
{

    public function testGetPromoCodeList()
    {
        $fetchPromoCodeService = new class () extends FetchPromoCodeService {
            public $client;

            public function __construct($client)
            {
                $this->client = (new JsonResponse(['a' => 1, 'b' => 2]))->getContent();
                parent::__construct($client);
            }
        };

        $result = $fetchPromoCodeService->getPromoCodeList();

        $this->assertIsArray($result);
    }
}

我需要测试getPromoCodeList() 方法,所以我想模拟http 调用。 测试的目的是确保我们将结果调用转换为 php 数组。

但我的问题在于FetchPromoCodeService 构造函数。执行命令时出现此错误。

ArgumentCountError: 函数参数太少 class@anonymous::__construct(), 0 传入 /var/www/html/tests/Service/FetchPromoCodeServiceTest.php 上 第 14 行,正好是 1 行

我知道它正在等待 HttpClientInterface 类型的参数,但我知道有一种方法可以覆盖它,因为我只想模拟 client 属性。我只是不记得我是怎么做到的。

如何在 php 和匿名类中做到这一点?

【问题讨论】:

    标签: php unit-testing symfony phpunit php-7


    【解决方案1】:

    @subCore 如果我错了,请告诉我,但根据你说的,我是这样做的,它似乎有效。

    <?php
    
    namespace App\Tests\Service;
    
    use App\Service\FetchPromoCodeService;
    use PHPUnit\Framework\TestCase;
    use Symfony\Component\HttpFoundation\JsonResponse;
    use Symfony\Contracts\HttpClient\HttpClientInterface;
    
    class FetchPromoCodeServiceTest extends TestCase
    {
        public function testGetPromoCodeList()
        {
            $client = $this->createMock(HttpClientInterface::class);
            $fetchPromoCodeService = new class ($client) extends FetchPromoCodeService {
                public $client;
                public function __construct($client)
                {
                    $codesMock = ['a' => 1, 'b' => 2];
                    $this->client = (new JsonResponse($codesMock))->getContent(); // mock client object;
                    parent::__construct($client);
                }
            };
    
            $result = $fetchPromoCodeService->getPromoCodeList();
    
            $this->assertIsArray($result);
        }
    }
    

    【讨论】:

      【解决方案2】:

      虽然你可以使用匿名类实现你想要的,但 Symfony HTTP 客户端附带的模拟客户端可能是更简单的解决方案:

      <?php
      
      namespace App\Tests\Service;
      
      use App\Service\FetchPromoCodeService;
      use PHPUnit\Framework\TestCase;
      use Symfony\Component\HttpClient\MockHttpClient;
      use Symfony\Component\HttpClient\Response\MockResponse;
      
      final class FetchPromoCodeServiceTest extends TestCase
      {
          public function testGetPromoCodeList()
          {
              $client = new MockHttpClient([new MockResponse(json_encode(['a' => 1, 'b' => 2]))]);
      
              $result = (new FetchPromoCodeService($client))->getPromoCodeList();
      
              self::assertIsArray($result);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-16
        • 1970-01-01
        • 1970-01-01
        • 2019-09-01
        • 2018-03-31
        • 1970-01-01
        • 2019-10-06
        • 1970-01-01
        相关资源
        最近更新 更多