Symfony2在测试中访问私有服务 [英] Symfony2 access private services in tests

查看:93
本文介绍了Symfony2在测试中访问私有服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我正在测试Symfony2中的某些服务,并且正在尝试使用Guzzle MockPlugin来控制CURL响应。使用Symfony版本2.3.8。我有一个有趣的行为,不确定这是否是Symfony2错误。



我在services.yml中有这些服务:

  lookup_service_client:
类:FOO
public:false
factory_service:lookup_client_builder
factory_method:构建

lookup_repository_auth_type:
类:AuthType
参数:[ @lookup_service_client]


lookup_repository_cancel_reason:
类:CancelReason
参数:[ @lookup_service_client]

payment_service_client:
类:FOO
public:假
factory_service:付款_客户端_生成器
factory_method:构建

Payment_repository:
类:Payment
参数:[ @payment_service_client]

类的名称并不重要。您可以看到 lookup_service_client和 lookup_service_client都是PRIVATE服务。



我有一个测试类,该类扩展了Symfony\Bundle\FrameworkBundle\Test\ TestWebTestCase。在一个测试中,我需要执行以下操作:

  $ 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'); =>返回服务实例

$ payment = $ this-> client-> getContainer()-> get(’payment_service_client’); =>返回一个异常,说:您请求的服务不存在

这两个拖曳之间的唯一区别service_client服务是 lookup_service_client被注入其他几个服务,而 payment_service_client仅被注入其他一个服务。



所以,问题是:


  1. 为什么我可以找回


  2. 为什么从容器 lookup_service_client中将其设置为私有?


  3. 为什么我可以检索 lookup_service_client,但由于唯一的原因而无法检索 payment_service_client


  4. 是否可以访问私有服务是Symfony2错误?



解决方案

在Symfony 4.1中对此进行了一些新更改:


在Symfony 4.1中,我们进行了相同的操作,现在测试允许默认情况下获取私有服务。


实际上,基于WebTestCase和KernelTestCase的测试现在可以通过$ client->访问特殊容器; getContainer()或static :: $ container属性,该属性允许获取未删除的私有服务。


您可以在< a href = https://symfony.com/blog/new-in-symfony-4-1-simpler-service-testing rel = nofollow noreferrer>新闻。


虽然这不是bug,但绝对与直观相反。 手册专门说:


现在该服务是私有的,您不应直接从容器中获取服务


$ container-> ; get('foo');


这可能会或可能不会生效,这取决于容器如何优化
服务实例,甚至在可行的情况下,已弃用
。简单地说:如果您不想让
的服务直接从代码中访问,则可以将其标记为私有。


核心团队已决定使此行为更加一致和直观在Symfony 4中:


在Symfony 3.2中不建议使用Container :: set()方法设置或取消私有服务,并且不再支持在4.0中;


在Container :: has()中检查私有服务是否存在,在Symfony 4.0中始终返回false;


请求一个Symfony 3.2中不推荐使用带有Container :: get()方法的私有服务,并且不再在4.0中返回该服务。



Currently I'm working on testing some services in Symfony2 and I'm trying to use Guzzle MockPlugin for controlling CURL responses. Symfony version 2.3.8 is used. I've got to an interesting behaviour and I'm not sure if this is a Symfony2 bug or not.

I have these services in 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"]

The name of the classes are not important. You can see that both "lookup_service_client" and "lookup_service_client" are PRIVATE services.

I have a test class, which extends Symfony\Bundle\FrameworkBundle\Test\WebTestCase. In one test I need to do something like:

$lookup = $this->client->getContainer()->get('lookup_service_client');

$payment = $this->client->getContainer()->get('payment_service_client');

I expected that, setting those services as PRIVATE, will not let me retrieve the services from container in tests, but the actual result is:

$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"

The only difference between those tow service_client services is that "lookup_service_client" is injected in several other services, while "payment_service_client" is injected in only one other service.

So, the questions are:

  1. Why I can retrieve from container "lookup_service_client", since I've set it to private?

  2. Why I can retrieve "lookup_service_client", but cannot retrieve "payment_service_client" since the only difference is presented above?

  3. Is it a Symfony2 bug that I can access private service?

解决方案

There were some new changes regarding this in Symfony 4.1:

In Symfony 4.1, we did the same and now tests allow fetching private services by default.

In practice, tests based on WebTestCase and KernelTestCase now access to a special container via $client->getContainer() or the static::$container property that allows to fetch non-removed private services.

You can read more about it in the news post.

While this is not a bug, it is definitely counter intuitive. The manual specifically says:

Now that the service is private, you should not fetch the service directly from the container:

$container->get('foo');

This may or may not work, depending on how the container has optimized the service instanciation and, even in the cases where it works, is deprecated. Simply said: A service can be marked as private if you do not want to access it directly from your code.

Which is why the core team has decided to make this behavior more consistent and intuitive in Symfony 4:

Setting or unsetting a private service with the Container::set() method is deprecated in Symfony 3.2 and no longer supported in 4.0;

Checking the existence of a private service with the Container::has() will always return false in Symfony 4.0;

Requesting a private service with the Container::get() method is deprecated in Symfony 3.2 and no longer returns the service in 4.0.

这篇关于Symfony2在测试中访问私有服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆