我正在为控制器编写功能测试。 它使用一个类从第三方网站导入一些数据,为此,我编写了一个我用于Symfony的类,为它设置服务。
现在,在我的功能测试中,我想用一个模拟的服务替换这个服务,将它设置在容器中并在我的功能测试中使用它。
所以我的代码如下:
// Mock the ImportDataManager and substitute it in the services container
$mockDataImportManager = $this->getMockBuilder('\AppBundle\Manager\DataImportManager')->disableOriginalConstructor()->getMock();
$client->getContainer()->set('shq.manager.DataImport', $mockDataImportManager);
$client->submit($form);
$crawler = $client->followRedirect();
据我所知,在每个请求之间,客户端重新启动内核,我必须再次设置模拟类,我在调用$ client-> submit之前立即设置模拟。
但是这种方法对我来说似乎不起作用,控制器仍然继续使用服务的真实版本而不是模拟的服务。
如何在模拟功能测试期间使用模拟类来避免调用远程网站?
如果我转储设置模拟服务,我可以看到它已正确设置:
dump($client->getContainer()->get('shq.manager.DataImport'));die;
返回
.SetUpControllerTest.php on line 145:
Mock_DataImportManager_d2bab1e7 {#4807
-__phpunit_invocationMocker: null
-__phpunit_originalObject: null
-em: null
-remotes: null
-tokenGenerator: null
-passwordEncoder: null
-userManager: null
}
但是在$form->submit($form)
通话期间未使用它,而是使用原始服务。
更新 继续寻找解决方案,我从Symfony项目登陆this GitHub page,用户要求解决我的同一问题。 第二个调用不使用他的类的模拟/替换版本,而是使用原始版本。
这是正确的行为吗?那么,我是否无法在第二次调用客户端时修改服务容器?
答案 0 :(得分:1)
然而,我不明白为什么服务没有在容器中替代,我也无法真正解决这个问题。
无论如何,我发现了某种解决方法,实际上更正确的解决方案(如果仍然不清楚为什么服务没有被替换,这是我想要解决的好奇心 - 也许是因为$ client-&gt ; submit()方法使用POST方法?)。
我的解决方法是简单的双倍测试。
我在AppBundle/Tests/TestDouble
中创建了一个新类,并将其命名为DataImportManagerTestDouble.php
。
它包含控制器使用的唯一方法:
namespace AppBundle\Tests\TestDouble;
use AppBundle\Entity\User;
class DataImportManagerTestDouble
{
public function importData(User $user)
{
return true;
}
}
然后,我通过以下方式在config_test.yml
(app/config/config_test.yml
)文件中实例化它:
services:
shq.manager.DataImport:
class: AppBundle\Tests\TestDouble\DataImportManagerTestDouble
这样,在测试期间,并且仅在测试期间,作为服务加载的类是TestDouble而不是原始类。 所以测试通过,我(相对)高兴。目前,至少。