使用私有方法在 Symfony 中测试服务
Test service in Symfony with private method
我试图在服务中测试 public 方法,但它调用了另一个私有方法。
这是一个测试class
<?php
use App\Core\Application\Service\Files\UploadedFileService;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use App\Core\Infrastructure\FileStorage\Services\ImagePath;
use App\Core\Infrastructure\FileStorage\Services\ImageResizeGenerator;
use Symfony\Component\Routing\RouterInterface;
class UploadedFileServiceTest extends TestCase
{
/** @var UploadedFileService */
private $instance;
private $parameterHandler;
private $router;
private $imageResizeGenerator;
private $imagePath;
public function setUp()
{
parent::setUp();
$this->parameterHandler = $this->prophesize(ParameterBagInterface::class);
$this->router = $this->prophesize(RouterInterface::class);
$this->imageResizeGenerator = $this->prophesize(ImageResizeGenerator::class);
$this->imagePath = $this->prophesize(ImagePath::class);
$this->instance = new UploadedFileService(
$this->parameterHandler->reveal(),
$this->router->reveal(),
$this->imageResizeGenerator->reveal(),
$this->imagePath->reveal()
);
}
public function testGetDefaultImageResponse()
{
$result = $this->instance->getDefaultImageResponse('user');
}
}
当我运行testGetDefaultImageResponse
测试时,在控制台日志中出现错误。
这是经过测试的功能
/**
* @param string $entity
*
* @return Response
*/
public function getDefaultImageResponse(string $entity)
{
return new Response(
$this->getDefaultImage($entity),
Response::HTTP_OK,
['Content-type' => 'image/jpg']
);
}
真正的问题在getDefaultImage()
抛出错误
file_get_contents(): Filename cannot be empty
这是私有方法的内容
/**
* @param string $entity
*
* @return bool|string
*/
private function getDefaultImage(string $entity)
{
switch ($entity) {
case 'entity1':
return file_get_contents($this->parameterHandler->get('images.default_avatar'));
case 'entity3':
return file_get_contents($this->parameterHandler->get('images.default_logo'));
}
return file_get_contents($this->parameterHandler->get('images.default_avatar'));
}
如何设置数据到$this->parameterHandler->get('images.default_avatar')
我在 运行ning 测试中哪里出错了?我必须承认我是单元测试的菜鸟。
问题是您的测试模拟,在本例中是 ParameterHandler 先知,模拟方法 get 具有默认行为,return为空。当调用方法时,它没有被告知要做什么,因此 file_get_contents() 将不会收到文件路径。
首先,你必须告诉你的先知return一个正确的文件路径:
$this->parameterHandler = $this->prophesize(ParameterBagInterface::class);
$this->parameterHandler->get('images.default_avatar')->willReturn('/your/path/avatar.jpg');
这将告诉先知 return /your/path/avatar.jpg 如果方法 get()使用参数 images.default_avatar 调用。如果您能够正确配置默认头像的路径,这应该可以工作。
您甚至可以通过添加 ->shouldBeCalled() 告诉 Prophet 必须调用此方法,但随后您将测试实际测试的内部结构 class (这种类型的测试有利有弊,取决于测试用例):
$this->parameterHandler->get('images.default_avatar')->willReturn('/your/path/avatar.jpg')->shouldBeCalled();
下一个挑战可能是将对 file_get_contents() 的调用抽象为一个新的 class,它也可以被模拟(例如出于速度和内存原因)。
我试图在服务中测试 public 方法,但它调用了另一个私有方法。
这是一个测试class
<?php
use App\Core\Application\Service\Files\UploadedFileService;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use App\Core\Infrastructure\FileStorage\Services\ImagePath;
use App\Core\Infrastructure\FileStorage\Services\ImageResizeGenerator;
use Symfony\Component\Routing\RouterInterface;
class UploadedFileServiceTest extends TestCase
{
/** @var UploadedFileService */
private $instance;
private $parameterHandler;
private $router;
private $imageResizeGenerator;
private $imagePath;
public function setUp()
{
parent::setUp();
$this->parameterHandler = $this->prophesize(ParameterBagInterface::class);
$this->router = $this->prophesize(RouterInterface::class);
$this->imageResizeGenerator = $this->prophesize(ImageResizeGenerator::class);
$this->imagePath = $this->prophesize(ImagePath::class);
$this->instance = new UploadedFileService(
$this->parameterHandler->reveal(),
$this->router->reveal(),
$this->imageResizeGenerator->reveal(),
$this->imagePath->reveal()
);
}
public function testGetDefaultImageResponse()
{
$result = $this->instance->getDefaultImageResponse('user');
}
}
当我运行testGetDefaultImageResponse
测试时,在控制台日志中出现错误。
这是经过测试的功能
/**
* @param string $entity
*
* @return Response
*/
public function getDefaultImageResponse(string $entity)
{
return new Response(
$this->getDefaultImage($entity),
Response::HTTP_OK,
['Content-type' => 'image/jpg']
);
}
真正的问题在getDefaultImage()
抛出错误
file_get_contents(): Filename cannot be empty
这是私有方法的内容
/**
* @param string $entity
*
* @return bool|string
*/
private function getDefaultImage(string $entity)
{
switch ($entity) {
case 'entity1':
return file_get_contents($this->parameterHandler->get('images.default_avatar'));
case 'entity3':
return file_get_contents($this->parameterHandler->get('images.default_logo'));
}
return file_get_contents($this->parameterHandler->get('images.default_avatar'));
}
如何设置数据到$this->parameterHandler->get('images.default_avatar')
我在 运行ning 测试中哪里出错了?我必须承认我是单元测试的菜鸟。
问题是您的测试模拟,在本例中是 ParameterHandler 先知,模拟方法 get 具有默认行为,return为空。当调用方法时,它没有被告知要做什么,因此 file_get_contents() 将不会收到文件路径。
首先,你必须告诉你的先知return一个正确的文件路径:
$this->parameterHandler = $this->prophesize(ParameterBagInterface::class);
$this->parameterHandler->get('images.default_avatar')->willReturn('/your/path/avatar.jpg');
这将告诉先知 return /your/path/avatar.jpg 如果方法 get()使用参数 images.default_avatar 调用。如果您能够正确配置默认头像的路径,这应该可以工作。
您甚至可以通过添加 ->shouldBeCalled() 告诉 Prophet 必须调用此方法,但随后您将测试实际测试的内部结构 class (这种类型的测试有利有弊,取决于测试用例):
$this->parameterHandler->get('images.default_avatar')->willReturn('/your/path/avatar.jpg')->shouldBeCalled();
下一个挑战可能是将对 file_get_contents() 的调用抽象为一个新的 class,它也可以被模拟(例如出于速度和内存原因)。