使用 PHP 匿名 Class 进行测试和模拟
Test and Mock by Using PHP Anonymous Class
我正在尝试使用匿名 class 测试和模拟一段代码。这是代码:
<?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();
}
}
这是我的测试Class:
<?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: Too few arguments to function
class@anonymous::__construct(), 0 passed in
/var/www/html/tests/Service/FetchPromoCodeServiceTest.php on
line 14 and exactly 1 expected
我知道它正在等待 HttpClientInterface
类型的参数,但我知道有一种方法可以覆盖它,因为我只想模拟 client
属性。我只是不记得我是怎么做到的。
如何在 php 和匿名 class 中做到这一点?
@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);
}
}
尽管您可以使用匿名 class 实现您想要的,但 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);
}
}
我正在尝试使用匿名 class 测试和模拟一段代码。这是代码:
<?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();
}
}
这是我的测试Class:
<?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: Too few arguments to function class@anonymous::__construct(), 0 passed in /var/www/html/tests/Service/FetchPromoCodeServiceTest.php on line 14 and exactly 1 expected
我知道它正在等待 HttpClientInterface
类型的参数,但我知道有一种方法可以覆盖它,因为我只想模拟 client
属性。我只是不记得我是怎么做到的。
如何在 php 和匿名 class 中做到这一点?
@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);
}
}
尽管您可以使用匿名 class 实现您想要的,但 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);
}
}