symfony - 如何在 symfony 4 上使用 PHPUnit 测试依赖注入
问题描述
在 symfony 4 项目中,许多服务/控制器需要日志。尝试利用 symfony 提供的特征和自动装配选项的优势,我创建了一个 loggerTrait,它将传递给不同的服务。
namespace App\Helper;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
trait LoggerTrait
{
/** @var LoggerInterface */
private $logger;
/** @var array */
private $context = [];
/**
* @return LoggerInterface
*/
public function getLogger(): LoggerInterface
{
return $this->logger;
}
/**
* @required
*
* @param LoggerInterface|null $logger
*/
public function setLogger(?LoggerInterface $logger): void
{
$this->logger = $logger;
}
public function logDebug(string $message, array $context = []): void
{
$this->log(LogLevel::DEBUG, $message, $context);
}
...
}
(灵感来自symfonycasts.com)
服务将使用此特征
namespace App\Service;
use App\Helper\LoggerTrait;
class BaseService
{
use LoggerTrait;
/** @var string */
private $name;
public function __construct(string $serviceName)
{
$this->name = $serviceName;
}
public function logName()
{
$this->logInfo('Name of the service', ['name' => $this->name]);
}
}
它工作得很好,但我无法成功测试它。
我试图在我的测试中扩展 KernelTestCase 以模拟 loggerInterface,但我收到Symfony\Component\DependencyInjection\Exception\InvalidArgumentException: The "Psr\Log\LoggerInterface" 服务是私有的,你不能替换它,这很有意义。
这是我的测试:
namespace App\Tests\Service;
use App\Service\BaseService;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class BaseServiceTest extends KernelTestCase
{
private function loggerMock()
{
return $this->createMock(LoggerInterface::class);
}
protected function setUp()
{
self::bootKernel();
}
/**
* @test
* @covers ::logName
*/
public function itShouldLogName()
{
// returns the real and unchanged service container
$container = self::$kernel->getContainer();
// gets the special container that allows fetching private services
$container = self::$container;
$loggerMock = $this->loggerMock();
$loggerMock->expect(self::once())
->method('log')
->with('info', 'Name of the service', ['name' => 'service_test']);
$this->logger = $container->set(LoggerInterface::class, $loggerMock);
$baseService = new BaseService('service_test');
var_dump($baseService->getLogger());
}
}
是否有解决方案可以在服务内测试这样的记录器?
解决方案
您可以将服务覆盖为public
(仅适用于test
环境),config_test.yml
如下所示:
services:
Psr\Log\LoggerInterface:
public: true
这通常用于测试私有服务。
推荐阅读
- c# - 如何在 C# 7.0 中使用 CodeContracts?
- terraform - 什么时候在 terraform 中定义变量?
- php - 如何使用 Ionic 4、mysql 和 Angular 7 进行身份验证和 Crud 操作?
- neo4j - iMac 上 Neo4j Desktop 的 config 文件夹和 bin 文件夹在哪里?
- tensorflow - Keras 中基于 F1/AUC 时期的指标
- spring - 未找到 c3p0 hsqldb 驱动程序类
- node.js - 如何将元数据添加到 mac/linux 上的文件夹
- mysql - 创建 Mysql 表
- android - 在styles.xml 中将对话框按钮更改为具有波纹效果的清除
- swift - Firebase 规则中关于 indexOn 的烦人问题