Symfony2 Controller Testing without Application

Controller testing using the WebTestCase requires a Symfony Kernel and with that a complete application. However you can just ship your own simple kernel with just the dependencies necessary to test your application. This way you can easily create functional tests for bundles without the bundle requiring an application.

Create a TestKernel

// Tests/Controller/App/AppKernel.php

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends Kernel
    public function registerBundles()
        $bundles = array(
            // Dependencies
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Symfony\Bundle\SecurityBundle\SecurityBundle(),
            new Symfony\Bundle\MonologBundle\MonologBundle(),
            new Symfony\Bundle\TwigBundle\TwigBundle(),
            new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
            new JMS\SerializerBundle\JMSSerializerBundle($this),
            new FOS\RestBundle\FOSRestBundle(),
            // My Bundle to test
            new Beberlei\WorkflowBundle\BeberleiWorkflowBundle(),

        return $bundles;

    public function registerContainerConfiguration(LoaderInterface $loader)
        // We don't need that Environment stuff, just one config

Creating the config.yml

# Tests/Controller/App/config.yml
    secret:          secret
    charset:         UTF-8
    test: ~
    router:          { resource: "%kernel.root_dir%/routing.yml" }
    form:            true
    csrf_protection: true
    validation:      { enable_annotations: true }
    templating:      { engines: ['twig'] }
        auto_start:     false

            type:         fingers_crossed
            action_level: error
            handler:      nested
            type:  stream
            path:  %kernel.logs_dir%/%kernel.environment%.log
            level: debug

Creating the routing.yml

# Tests/Controller/App/routing.yml
    resource: "@BeberleiWorkflowBundle/Controller/"
    type:     annotation
    prefix:   /

Adding a PHPUnit bootstrap

I assume the setup that Henrik described in his “Travis & Composer sitting in a Tree K-I-S-S-I-N-G” blog post.

His setup is missing the spl_autoload_register() call in the bootstrap file though.

// Tests/bootstrap.php
$loader = @include __DIR__ . '/../vendor/.composer/autoload.php';
if (!$loader) {
You must set up the project dependencies, run the following commands:
php composer.phar install
\Doctrine\Common\Annotations\AnnotationRegistry::registerLoader(array($loader, 'loadClass'));

spl_autoload_register(function($class) {
    if (0 === strpos($class, 'Beberlei\\WorkflowBundle\\')) {
        $path = __DIR__.'/../'.implode('/', array_slice(explode('\\', $class), 2)).'.php';
        if (!stream_resolve_include_path($path)) {
            return false;
        require_once $path;
        return true;

That means your bundle should have a composer.json that loads all the dependencies.

Modifying the phpunit.xml.dist

We have to tell the WebTestCase base class where to find this kernel:

<!-- phpunit.xml.dist -->
<phpunit bootstrap="Tests/bootstrap.php">
        <server name="KERNEL_DIR" value="Tests/Controller/App" />

Now just run your web-test cases.

If you want to debug the logging happening inside the Kernel just comment out the Monolog lines to get the log-messages printed to the screen.

You have to add the Tests/App/cache and Tests/App/logs to your version control ignore files.

More about: Symfony