【问题标题】:Controlling dependencies in Symfony tests控制 Symfony 测试中的依赖关系
【发布时间】:2019-12-01 02:08:48
【问题描述】:

我为我的 Symfony 4.2 应用程序进行了许多边缘到边缘测试。我的意思是使用测试客户端发出 Web 请求然后对结果进行断言的测试。示例:

public function testPageNotFound() {
    $client = $this->createClient();
    $client->request('GET', 'does-not-exist');
    $this->assertSame(404, $client->getResponse()->getStatusCode());
}

有没有办法在此类测试中更改服务容器中的特定服务?

示例问题:我的服务通过名为 FileFetcher 的抽象来发出 Web 请求。对于我的测试,我希望使用NullFileFetcher,这样就不会发出真正的网络请求。我如何告诉 Symfony 使用这个测试替身?

令人惊讶的是,在主要测试文档https://symfony.com/doc/current/testing.html 中没有关于如何执行此基本测试任务的信息。

我尝试的一种方法是在config/packages/test/services.yaml 中进行配置。这不起作用,据我所知是由 Symfony 不允许覆盖 services.yaml 引起的,因为它最后加载了主 config/services.yamlhttps://symfony.com/doc/current/configuration.html#configuration-environments

最后我想做的就是遵循一些非常基本的测试最佳实践:

  1. 在每个测试方法执行开始时初始化整个环境
  2. 可能将特定服务和配置更改为远离默认设置
  3. 执行被测代码并对结果进行断言

任何使用 Symfony 的代码示例将不胜感激。

【问题讨论】:

    标签: php symfony testing mocking symfony4


    【解决方案1】:

    文档需要更新:覆盖先前定义的最后一个文件是 config/services_test.yaml 这应该可以帮助您解决用例。 见https://github.com/symfony/recipes/blob/master/symfony/framework-bundle/4.2/src/Kernel.php#L42

    【讨论】:

    • 我已将其与 atymic 他们的答案相结合,并将服务更改为仅在测试模式下是合成的。效果很好。但是也有兴趣查看一些来自真正了解 Symfony 的人创建的真实项目的 services_test.yaml 文件。知道吗?
    【解决方案2】:

    您应该能够通过在容器中交换它来覆盖测试中的服务

    $this->container->getDefinition('x.x_service')->setSynthetic(true);
    $this->container->set('x.x_service', new NullFileFetcher());
    

    【讨论】:

    • $kernel->getContainer() 没有getDefinition 方法或任何带有definition 的方法。现在我知道了 Synthetic 的概念,我发现我可以把它放在我的 services.yaml 中,然后使我的测试与 test double 一起工作,但同时使生产代码失败,因为现在它不再构造 FileFetcher按需提供。
    猜你喜欢
    • 1970-01-01
    • 2011-04-22
    • 1970-01-01
    • 2016-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-20
    相关资源
    最近更新 更多