Home > Mobile >  Api Platform/Symfony and PHPUnit - How to inject a Service into an ApiTestCase (multiple constructor
Api Platform/Symfony and PHPUnit - How to inject a Service into an ApiTestCase (multiple constructor

Time:06-17

I have a BaseClass that extends the ApiTestCase of PHPUnit. Now in order to generate the Endpoint-URLs, I would like to be able to get the IRI of a given Entity, so, naive as I am, I tried to autowire the IriConverter into the BaseClass.

This throws an error, because autowiring does not detect the first argument to be an injected service. Also tried to manually define the $conv argument to be the api_platform.iri_converter in the services.yaml.

    public function __construct(IriConverter $conv, ?string $name = null, array $data = [], $dataName = '')
    {
        parent::__construct($name, $data, $dataName);
        $this->iriConverter = $conv;
     }

I do not know if Api Platform has a faulty Setter-Injection integration, but this is not working either. I also tried manually calling that function by declaring the "call" property of that Service in services.yaml, but no luck.

    /** @required */
    public function setConverter(IriConverter $conv): void
    {
        $this->iriConverter = $conv;
    }

Due to the IriConverter being inlined or removed when the container is compiled, this is not working either. Rather it is recommended to inject the service in the constructor, but how do I do that?

    public function setUp(): void
    {
        self::bootKernel();

        $this->iriConverter = self::$kernel->getContainer()->get('api_platform.iri_converter');

        // this right here throws a ServiceNotFound Exception - "The "kernel" service is synthetic, it needs to be set at boot time before it can be used."
        // $this->iriConverter = self::$container->get('api_platform.iri_converter');
    }

Thank you for reading this far!

CodePudding user response:

You don't have to boot the kernel manually, it is done automatically when using self::getContainer(). I have this in one of my Symfony 5.4 tests.

use ApiPlatform\Core\Api\IriConverterInterface;

private IriConverterInterface $iriConverter;

protected function setUp(): void
{
    $this->iriConverter = self::getContainer()->get(IriConverterInterface::class);
}

CodePudding user response:

Alright I found a solution.

The issue lies with fetching the IriConverter-Service inside the setUp()-function, because at this point the kernel is still booting, so no container is available.

I use the IriConverter only in one function and it looks like this:

    protected function getEntityIri(): string {
        if (!$this->iriConverter) {
            $this->iriConverter = self::$container->get(IriConverterInterface::class);
        }
        return $this->iriConverter->getIriFromResourceClass($this->getEntityClass());
    }

The IriConverter is fetched from the container on demand.

  • Related