Functional tests inside a standalone Symfony2's bundle Functional tests inside a standalone Symfony2's bundle symfony symfony

Functional tests inside a standalone Symfony2's bundle


Here is my own solution (I summarize all the process for testing in a standalone bundle):

1. First, a good bundle has its own composer.json to define its dependencies:

{    "name": "my/own-bundle",    "type": "symfony-bundle",    "description": "Symfony2 bundle that provides ...",    "keywords": ["my","own"],    "license": "MIT",    "authors": [        {            "name": "John Doe",            "email": "john.doe@omg.wtf"        }    ],    "require": {        "php": ">=5.3.2",        "symfony/framework-bundle": ">=2.3"    },    "require-dev": {        "phpunit/phpunit": "3.7.*"    },    "autoload": {        "psr-0": { "My\\OwnBundle": "" }    },    "target-dir": "My/OwnBundle",    "minimum-stability": "dev"}

Note the use of the dependency on symfony/framework-bundle which is needed for our tests on services. You certainly can lower the dependencies in specifying your own real dependencies on the symfony core.

With this file I can process the command (do it) to build the vendor directory of my bundle:

$ composer update

2. Then, I set my phpunit config file:

<!-- phpunit.xml.dist --><?xml version="1.0" encoding="UTF-8"?><phpunit backupGlobals="false"         backupStaticAttributes="false"         colors="true"         convertErrorsToExceptions="true"         convertNoticesToExceptions="true"         convertWarningsToExceptions="true"         processIsolation="false"         stopOnFailure="false"         syntaxCheck="false"         bootstrap="Tests/bootstrap.php">    <testsuites>        <testsuite name="MyOwnBundle Test Suite">            <directory>./Tests/</directory>        </testsuite>    </testsuites>    <filter>        <whitelist>            <directory>./</directory>            <exclude>                <directory>./Resources</directory>                <directory>./Tests</directory>                <directory>./vendor</directory>            </exclude>        </whitelist>    </filter></phpunit>

3. Then, I set the php bootstrap for the autoload of the class in my test directory:

// Tests/bootstrap.php$file = __DIR__.'/../vendor/autoload.php';if (!file_exists($file)){    $file = __DIR__.'/../../../../../../vendor/autoload.php';    if (!file_exists($file))        throw new RuntimeException('Install dependencies to run test suite.');}$autoload = require_once $file;

These steps are standard for any test in a standalone bundle.

4. Now, I want to simulate an application to make some functionnal tests on my services:

I need a kernel class:

// Tests/AppKernel.php (you can define it in a subdirectory /Fixtures if you prefer)use Symfony\Component\HttpKernel\Kernel;use Symfony\Component\Config\Loader\LoaderInterface;class AppKernel extends Kernel{    public function registerBundles()    {        $bundles = array();        if (in_array($this->getEnvironment(), array('test'))) {            $bundles[] = new Symfony\Bundle\FrameworkBundle\FrameworkBundle();            $bundles[] = new My\OwnBundle\MyOwnBundle();        }        return $bundles;    }    public function registerContainerConfiguration(LoaderInterface $loader)    {        $loader->load(__DIR__.'/config.yml');    }}

And the corresponding config.yml:

# Tests/config.ymlframework:    secret: test    session:        storage_id: session.storage.mock_filemy_own:    test: 2

Here is an example with a mock for the session. Don't forget to specify the correct framework configuration nodes if you want to have access to some services (if you don't specify the node session, you have no service session for instance).

5. Finally, I can retrieve my services like the following in my test classes:

// Tests/Functional/Handling/Handler.phpnamespace My\OwnBundle\Tests\Functional\Handling;use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;class HandlerTest extends WebTestCase{    private $handler;    protected function setUp()    {        require_once __DIR__.'/../../AppKernel.php';        $kernel = new \AppKernel('test', true);        $kernel->boot();        $container = $kernel->getContainer();        $this->handler = $container->get('my_own.handling.handler');    }    public function testHandle()    {        $this->assert($this->handler->handle());    }}