Overwriting Symfony 3.3 container services in controller tests
Asked Answered
E

1

7

I have a series of tests for controllers that rely on 3rd-party APIs that need to be mocked out in the test environment. We override the functional test client crawler and mock out the dependencies we need to test with. The key here is that the mocks change on every test.

In Symfony 3.2 this worked fine but in Symfony 3.3 I have a number of deprecation warnings due to the way the services are now injected:

An example controller test case:

class MyControllerTest extends WebTestCase
{
    private static $kernelModifier = null;

    public function setKernelModifier(\Closure $kernelModifier)
    {
        self::$kernelModifier = $kernelModifier;
        $this->ensureKernelShutdown();
    }

    protected static function createClient(array $options = [], array $server = [])
    {
        static::bootKernel($options);

        if ($kernelModifier = self::$kernelModifier) {
            $kernelModifier->__invoke();
            self::$kernelModifier = null;
        };

        $client = static::$kernel->getContainer()->get('test.client');
        $client->setServerParameters($server);

        return $client;
    }

    protected function getPropertyClient()
    {
        $mockService = (new PropertyMock())->getPropertyMock();
        $this->setKernelModifier(function () use ($mockService) {
            static::$kernel->getContainer()->set('app.property_service', $mockService);
        });
        return static::createClient();
    }

    protected function getPropertyFailureClient()
    {
        $mockService = (new PropertyMock())->getPropertyFailureMock();
        $this->setKernelModifier(function () use ($mockService) {
            static::$kernel->getContainer()->set('app.property_service', $mockService);
        });
        return static::createClient();
    }
}

The actual test:

public function testInvalidPropertyRequest()
{
    $client = $this->getPropertyClient();
    $client->request(
        'POST',
        '/webhook/property',
        [],
        [],
        [],
        ''
    );
    $this->assertEquals(400, $client->getResponse()->getStatusCode());
}

The deprecation error:

Setting the "app.property_service" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0: 3x

I've been through the 3.3 release documentation, BC breaks and deprecations and can't figure out how I would go about replacing container services with mocks after they've been configured.

Any help is appreciated.

Euphorbia answered 7/6, 2017 at 4:45 Comment(2)
Maybe this can help you: https://mcmap.net/q/1227942/-symfony-3-3-service-mocks-for-functional-testsDenotation
@Denotation Thanks for that. We solved it eventually by refactoring our tests so that they no longer needed to modify the container.Euphorbia
P
2

I'm also facing this issue and there's no hint within the Container class on how to handle this deprecation.

// for all interested, there's a current issue open on github - but no real solution other than either have a lot more bootstrapping code for your unit tests or moving to test the controllers in isolation. I'd recommend to have all controllers defined as services with fixed/defined dependiencies and no direct DIC usage.

Prytaneum answered 6/7, 2017 at 12:18 Comment(1)
They admitted they went a bit too far in this PR so I guess it's kinda safe to rely on this.Magnien

© 2022 - 2024 — McMap. All rights reserved.