目前,我正在测试Symfony2中的某些服务,而我正试图使用Guzzle MockPlugin来控制CURL响应。使用Symfony版本2.3.8。我有一个有趣的行为,我不确定这是否是一个Symfony2错误。
我在services.yml中有这些服务:
lookup_service_client:
class: FOO
public: false
factory_service: lookup_client_builder
factory_method: build
lookup_repository_auth_type:
class: AuthType
arguments: ["@lookup_service_client"]
lookup_repository_cancel_reason:
class: CancelReason
arguments: ["@lookup_service_client"]
payment_service_client:
class: FOO
public: false
factory_service: payment_client_builder
factory_method: build
payment_repository:
class: Payment
arguments: ["@payment_service_client"]
类的名称并不重要。你可以看到" lookup_service_client"和" lookup_service_client"是私人服务。
我有一个测试类,它扩展了Symfony \ Bundle \ FrameworkBundle \ Test \ WebTestCase。在一次测试中,我需要做一些事情:
$lookup = $this->client->getContainer()->get('lookup_service_client');
$payment = $this->client->getContainer()->get('payment_service_client');
我希望将这些服务设置为PRIVATE,不会让我在测试中从容器中检索服务,但实际结果是:
$lookup = $this->client->getContainer()->get('lookup_service_client'); => returns the service instance
$payment = $this->client->getContainer()->get('payment_service_client'); => returns an exception saying: "You have requested a non-existent service"
这两个service_client服务之间的唯一区别是" lookup_service_client"注入了其他几项服务,而#34; payment_service_client"仅注入其他一项服务。
所以,问题是:
为什么我可以从容器" lookup_service_client"中检索,因为我已将其设置为私有?
为什么我可以检索" lookup_service_client",但无法检索" payment_service_client"因为上面只介绍了唯一的区别吗?
我可以访问私人服务是否是Symfony2错误?
答案 0 :(得分:1)
Symfony 4.1中有一些新的变化:
在Symfony 4.1中,我们做了同样的事情,现在测试允许默认提取私有服务。
实际上,基于WebTestCase和KernelTestCase的测试现在可以通过$ client-> getContainer()或static :: $ container属性访问特殊容器,该属性允许获取未删除的私有服务。
您可以在news post中了解更多相关信息。
虽然这不是一个错误,但它肯定是反直觉的。 manual具体说:
现在该服务是私有的,您不应该获取该服务 直接来自容器:
$container->get('foo');
根据容器的优化方式,这可能有效,也可能无效 服务实例,即使在工作的情况下,也是如此 弃用。简单地说:如果你这样做,服务可以被标记为私人 不想直接从您的代码访问它。
这就是核心团队在Symfony 4中决定make this behavior more consistent and intuitive的原因:
在Symfony 3.2中不推荐使用Container :: set()方法设置或取消设置私有服务,4.0中不再支持;
使用Container :: has()检查是否存在私有服务将始终在Symfony 4.0中返回false;
在Symfony 3.2中不推荐使用Container :: get()方法请求私有服务,并且不再在4.0中返回该服务。
答案 1 :(得分:0)
2018和Symfony 3.4 / 4.0是此问题的最佳解决方案(目前为止)
此方法with all its pros/cons is described in this post with code examples。
访问私有服务的最佳解决方案是添加编译器通行证,使所有服务公开以进行测试。而已。它在实践中看起来如何?
use Symfony\Component\HttpKernel\Kernel;
+use Symplify\PackageBuilder\DependencyInjection\CompilerPass\PublicForTestsCompilerPass;
final class AppKernel extends Kernel
{
protected function build(ContainerBuilder $containerBuilder): void
{
$containerBuilder->addCompilerPass('...');
+ $containerBuilder->addCompilerPass(new PublicForTestsCompilerPass());
}
}
PublicForTestsCompilerPass
的样子:
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
final class PublicForTestsCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $containerBuilder): void
{
if (! $this->isPHPUnit()) {
return;
}
foreach ($containerBuilder->getDefinitions() as $definition) {
$definition->setPublic(true);
}
foreach ($containerBuilder->getAliases() as $definition) {
$definition->setPublic(true);
}
}
private function isPHPUnit(): bool
{
// defined by PHPUnit
return defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__');
}
}
要使用此类,只需按以下方式添加包:
composer require symplify/package-builder
但是,当然,更好的方法是使用自己的类,满足您的需求(您可能需要测试等)。
然后您的所有测试都会按预期继续工作!
请告诉我,这对您有何帮助。
答案 2 :(得分:-1)
在容器中检查它们:
container:debug lookup_service_client
container:debug payment_service_client
在你的例子中,他们都有“FOO”类,也许就是这种情况