如何在功能测试中使用symfony 4模拟服务?

abr*_*low 6 service dependency-injection functional-testing symfony

我有一个Commandbus处理程序,它注入了一些服务:

class SomeHandler
{
    private $service;

    public function __construct(SomeService $service)
    {
        $this->service = $service;
    }

    public test(CommandTest $command)
    {
        $this->service->doSomeStuff();
    }
}
Run Code Online (Sandbox Code Playgroud)

SomeService的方法doSomeStuff具有外部调用,我不想在测试期间使用它。

class SomeService
{
    private $someBindedVariable;

    public function __construct($someBindedVariable)
    {
        $this->someBindedVariable = $someBindedVariable;
    }

    public function doSomeStuff()
    {
        //TODO: some stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

在测试中,我尝试用模拟对象替换服务

public function testTest()
{
    $someService = $this->getMockBuilder(SomeService::class)->getMock();
    $this->getContainer()->set(SomeService::class, $someService);

    //TODO: functional test for the route, which uses SomeHandler
}
Run Code Online (Sandbox Code Playgroud)

第一个问题是该代码将引发异常““ App \ Service \ SomeService”服务是私有的,您无法替换它。”

好的,让我们尝试将其公开:

services.yaml:

App\Service\SomeService:
    public: true
    arguments:
        $someBindedVariable: 200
Run Code Online (Sandbox Code Playgroud)

但这没有帮助。我从本地SomeService得到响应。让我们尝试使用别名:

some_service:
    class: App\Service\SomeService
    public: true
    arguments:
        $someBindedVariable: 200

App\Service\SomeService:
    alias: some_service
Run Code Online (Sandbox Code Playgroud)

再一次,模拟对象不被测试使用。我看到来自本地SomeService的响应。

我试图附加自动装配选项,但没有帮助。

在测试期间,我该如何在整个项目中用某些模拟对象替换SomeService?

小智 5

要模拟和测试服务,您可以放置​​以下配置:

配置/包/测试/service.yaml

'test.myservice_mock':
    class: App\Service\MyService
    decorates: App\Service\MyService
    factory: ['\Codeception\Stub', makeEmpty]
    arguments:
      - '@test.myservice_mock.inner'
Run Code Online (Sandbox Code Playgroud)

  • 您能详细说明一下吗? (3认同)

Don*_*sto 4

最好的方法是显式定义该服务并使其成为参数化的,以便您注入的类可以基于环境参数(因此,基本上,为您正在服务的测试和开发定义不同的实现尝试注入)。

基本上,类似

<service id="yourService">
  <argument type="service" id="%parametric.fully.qualified.class.name%" />
</service>
Run Code Online (Sandbox Code Playgroud)

然后你可以在common.yamlFQCN中定义真正的实现

parameters:
    parametric.fully.qualified.class.name: Fully\Qualified\Class\Name\Real\Impl
Run Code Online (Sandbox Code Playgroud)

以及test.yaml(应该在之后 common.yaml加载以覆盖它)存根实现

parameters:
    parametric.fully.qualified.class.name: Fully\Qualified\Class\Name\Stub\Impl
Run Code Online (Sandbox Code Playgroud)

您无需触及任何代码行或测试文件行即可完成:只需配置。

注意

这只是一个概念性和说明性的示例,您应该将其适应您的代码(例如,请参阅common.yaml和)和您的类名称(请参阅和所有 FQCN 内容)test.yamlyourService

而且在 symfony 4 中,配置文件可以被.env文件替换以获得相同的结果,你只需要适应这些概念。