The ContainerTest

This is a short post before the weekend about testing in applications with dependency injection container (DIC). This solution helps me with a problem that I occasionally trip over in environments with large amounts of services connected through a DIC.

The problem is forgetting to adjust the DIC configuration when you add a new or remove a dependency to a service. This can easily slip through into production if you rely on your functional- and unit-tests to catch the problem.

I can avoid this problem by adding a functional test in my application that instantiate all the various services and checks if they are created correctly. The first time I saw this pattern was during development of some of the early Symfony2 bundles, most notably DoctrineBundle.

<?php

namespace Acme;

class ContainerTest extends \PHPUnit_Framework_TestCase
{
    use SymfonySetup;

    public static function dataServices()
    {
        return array(
            array('AcmeDemoBundle.FooService', 'Acme\DemoBundle\Service\FooService'),
            array('AcmeDemoBundle.BarController', 'Acme\DemoBundle\Controller\BarController'),
        );
    }

    /**
     * @test
     * @dataProvider dataServices
     */
    public function it_creates_service($id, $class)
    {
        $service = $this->getContainer()->get($id);
        $this->assertInstanceOf($class, $service);
    }
}

Whenever you create or modify a service check the ContainerTest if its already guarded by a test. Add a test if necesary and then make the change. It’s as easy as that.

The SymfonySetup trait provides access to the Symfony DIC using getContainer() as you can see in the test method. See my blog post on traits in tests for more information.

More about: Symfony / Testing