Symfony 4.2如何为测试公开一个服务

6
我有一个解决方案,可以使服务公开。在services.yml文件中实现。
    test_phpdocxService:
          alias: App\Service\PhpDocxService
          public: true

我尝试访问该服务:

$container = self::$container;
$phpDocxService = $container->get('test_phpdocxService');

$this->filename = $phpDocxService->generateDocxDocument('docx/aaa.html.twig', $data);

但我觉得这样做不太好。有没有其他的方法?

1
simpler-service-testing 对你不起作用吗? - Cerad
不,它在Symfony 4.2中不起作用。 - olek07
通常我很欣赏问题的简洁明了。但是,不得不浏览数百行代码真是让人头痛,但在这种情况下,我认为我们需要再多一点点信息。请复制/粘贴链接示例中的WebTestCase,然后调整服务名称。你是否会收到“找不到服务错误”的提示? - Cerad
使用链接文章中的方法,您应该请求“App\Service\PhpDocxService”,而不是“test_phpdocxService”。 - Cerad
我也不工作了。Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException : 容器编译时,"App\Service\PhpDocxService" 服务或别名已被删除或内联。你应该把它设为公有的,或停止直接使用容器而改用依赖注入。我使用 $phpDocxService = $container->get(\App\Service\PhpDocxService::class); 的方式。 - olek07
显示剩余3条评论
4个回答

9
好的。所以有一个问题,与测试未在应用程序中使用的私有服务有关。它仍然处于开放状态并正在讨论中,但基本上,现在您需要在应用程序的某个地方对您的私有服务进行类型提示,然后才能在测试中访问它。
使用新的4.4.2安装:
# src/Service/PhpDocxService.php
namespace App\Service;
class PhpDocxService
{
    public function sayHello()
    {
        return 'hello';
    }
}

# src/Controller/MyController.php
namespace App\Controller;

use App\Service\PhpDocxService;


class MyController
{
    #****** This is the secret ******
    public function __construct(PhpDocxService $phpDocxService)
    {

    }
}

# src/tests/MyTest.php
namespace App\Tests;

use App\Service\PhpDocxService;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class MyTest extends WebTestCase
{
    public function testServiceFound()
    {
        self::bootKernel();

        // gets the special container that allows fetching private services
        $container = self::$container;

        $phpDocxService = $container->get(PhpDocxService::class);

        $this->assertEquals('hello',$phpDocxService->sayHello());
    }
}

在控制器的构造函数中为您的服务添加类型提示,一切都将按预期工作。


1
在构造函数中也无法工作 Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException:当容器编译时,“App\Service\PhpDocxService”服务或别名已被删除或内联。您应该将其公开,或停止直接使用容器并改用依赖注入。 - olek07
我想,我的错误是我忘记了 self::bootKernel(); - olek07
@olek07 我猜你现在对整个事情已经感到相当沮丧了。可能尝试了很多方法。休息一下,然后回来创建一个新项目。添加我上面发布的三个文件并验证它是否按预期工作。它肯定会的。然后也许可以回去弄清楚为什么它在你当前的项目中不起作用。是的,启动内核有点重要。 - Cerad
我在你的问题中没有看到任何关于服务模拟的内容。这是一个完全不同的问题,如果可能的话最好避免使用。 - Cerad
1
谢谢@Cerad解释了“未使用的服务”是什么意思! - erop
显示剩余8条评论

8

3

不需要!:)

相反,您可以使用Symfony 4.1中实现的新更简单的服务测试

通过这个,基于WebTestCase和KernelTestCase的测试现在可以通过static::$container属性访问一个特殊的容器,从而允许获取非删除的私有服务

这意味着,如果您使用该容器,私有服务在测试中会自动变为公共服务。

只需执行以下操作:

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class SomeClassToTest extends WebTestCase
{
    public function getService(string $service)
    {
        self::bootKernel();
        $container = self::$kernel->getContainer();
        $container = self::$container;

        return self::$container->get($service);
    }

    public function tesSomething()
    {
        $imageProcessor = $this->getService('app.some.service');
    }

现在,您可以在测试环境中获取私有的'app.some.service'服务。

1
当然可以啊,我在我的项目中使用它,而且我使用的是Symfony 4.2。 - Eduardo Fernandes
1
可以确认这也是有效的。只要小心不要重复启动内核即可。 - Dean
可以确认,请勿重复启动内核。 - Med

0

自动装配从Symfony 3.4开始存在,但在4.x版本中,默认情况下已被激活。

因此,您在/src目录中的所有类都是公共的,并设置为服务。

转到/config/services.yaml,您会找到这段代码:

services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

这意味着你的 /src/Services/PhpDocxService.php 文件可以被 App/Services/PhpDocxService 调用。
你找到的解决方案是通过 $this->getContainer()->get('test_phpdocxService'); 来调用你的服务。

是的,但我认为仅在测试中在services.yml中定义别名是一个不好的解决方案。有更好的方法吗? - olek07

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接