目前我正在测试 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”都是私有(private)服务。
我有一个测试类,它扩展了 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”被注入(inject)到其他几个服务中,而“payment_service_client”仅被注入(inject)到另一个服务中。
所以,问题是:
为什么我可以从容器“lookup_service_client”中检索,因为我已将其设置为私有(private)?
为什么我可以检索到“lookup_service_client”,但不能检索到“payment_service_client”,因为唯一的区别如上所示?
是不是Symfony2的bug导致我可以访问私服?
最佳答案
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.
您可以在 news post 中阅读更多相关信息.
虽然这不是错误,但绝对违反直觉。 manual具体说:
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.
这就是核心团队决定 make this behavior more consistent and intuitive 的原因在 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.
关于php - Symfony2 在测试中访问私有(private)服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27604266/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/