Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overwriting Symfony 3.3 container services in controller tests

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.

like image 939
Tom Jowitt Avatar asked Jun 07 '17 04:06

Tom Jowitt


1 Answers

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.

like image 158
maschmann Avatar answered Oct 04 '22 01:10

maschmann