问题
I have the solution to make the service public. In the services.yml
test_phpdocxService:
alias: App\Service\PhpDocxService
public: true
I try to access the service:
$container = self::$container;
$phpDocxService = $container->get('test_phpdocxService');
$this->filename = $phpDocxService->generateDocxDocument('docx/aaa.html.twig', $data);
But I find it not so nice. Is there an another way to do that?
回答1:
You need to create in config/config_test.yml
and declare that service is public and other configuration for tests there .
This approach you can use in symfony 3/4.
You can read tutorial here: https://symfonycasts.com/screencast/phpunit/integration-tests
About Symfony simple testing 4.1 feature please read @Cerad post
回答2:
Okay. So there is an issue about testing private services that are not used anywhere in your app. It is still open and being discussed but basically, for now, you need to typehint against your private service somewhere in your app before you can access it in a test.
Using a fresh 4.4.2 install:
# 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());
}
}
Typehint your service in a controller's constructor and everything works as expected.
回答3:
The autowiring exists Since Symfony 3.4 but with the 4.x version, it is activated by default.
So, all your class inside /src directory is public and setted as services.
Go to /config/services.yaml, you'll find this code:
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}'
This means that your /src/Services/PhpDocxService.php file is callable by App/Services/PhpDocxService
The solution what you found is to call your service by $this->getContainer()->get('test_phpdocxService');
回答4:
YOU DON'T! :)
Instead, you use the new Simpler service testing, implemented in Symfony 4.1.
With that, tests based on WebTestCase and KernelTestCase now access to a special container via the static::$container property that allows fetching non-removed private services.
And that means that private services are automatically public in tests if you use that container.
Just do something like:
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');
}
And now you can get the private 'app.some.service' service in testing environments.
来源:https://stackoverflow.com/questions/54466158/symfony-4-2-how-to-do-a-service-public-only-for-tests