Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why PHPunit asks for KERNEL_DIR using Silex?

I'm trying to setup unit tests for my Silex application but I keep getting this error message:

RuntimeException: Either set KERNEL_DIR in your phpunit.xml according to http://symfony.com/doc/current/book/testing.html#your-first-functional-test or override the WebTestCase::createKernel() method.

This is my ./app/phpunit.xml.dist:

<?xml version="1.0" encoding="UTF-8"?>

<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit
    backupGlobals="false"
    backupStaticAttributes="false"
    colors="true"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    processIsolation="false"
    stopOnFailure="false"
    syntaxCheck="false"
    bootstrap="phpunit_bootstrap.php"
>
    <testsuites>
        <testsuite name="Project Test Suite">
            <directory>../src/Acme/*/Tests</directory>
        </testsuite>
    </testsuites>

    <!--<php>-->
        <!--<server name="KERNEL_DIR" value="/var/www/acme/api/app/" />-->
    <!--</php>-->
</phpunit>

This is my ./app/phpunit_bootstrap.php (that include composer's autoloader):

<?php

if (!@include __DIR__ . '/../../vendor/autoload.php') {
    die(<<<'EOT'
You must set up the project dependencies, run the following commands:
wget http://getcomposer.org/composer.phar
php composer.phar install
EOT
    );
}

My directory structure is the following:

Silex application tree structure

It looks like phpunit is looking for *Kernel.php but I don't know why.

Here is my unit test:

<?php

namespace Acme\User\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class UserControllerTest extends WebTestCase
{
    protected $headers;

    protected function setUp()
    {
        $this->headers = array(
            'CONTENT_TYPE' => 'application/json',
        );
    }

    public function testAuthUser()
    {
        $client = static::createClient();

        $client->request('POST', ...);

        // Check the response content type
        $this->assertTrue(
            $client->getResponse()->headers->contains(
                'Content-Type',
                'application/json'
            )
        );

        // Assert that the response status code is 2xx
        $this->assertTrue($client->getResponse()->isSuccessful());

        $response = json_decode($client->getResponse()->getContent(), true);

        var_dump($response);die;
    }
}
like image 496
maxwell2022 Avatar asked Mar 04 '14 01:03

maxwell2022


1 Answers

Ok,

I've managed to make it work. I had several configuration issues.

The first one in my app/phpunit_boostrap.php, I've added:

<?php

$_SERVER['env'] = 'test';
...

Then in my web/index.php I've added:

// Return the kernel instead to run it if we are unit testing
if ('test'  == $app['mode']) {
    return $app;
}

$app->run();

Then in my app/application.php, I've added:

...
// Set dev mode for unit testing
if (isset($_SERVER['env']) && 'test' === $_SERVER['env']) {
    $app['mode'] = 'test';
}
...

I've noticed that I was not using the correct WebTestCase, Silex has its own where you need to create the application (set the kernel):

<?php

namespace Acme\User\Tests\Controller;

// Notice the Silex class for the WebTestCase
use Silex\WebTestCase;

class UserControllerTest extends WebTestCase
{
    protected $headers;

    public function createApplication()
    {
        // index.php should return the $app instead to run() it
        return require __DIR__ . '/../../../../../web/index.php';
    }

    protected function setUp()
    {
        // Don't forget to call the parent setup that is setting the kernel
        parent::setUp();
        $this->headers = array(
            'CONTENT_TYPE' => 'application/json',
        );
    }

    public function testAuthUser()
    {
        // Create a client this way
        $client = $this->createClient();

        $client->request('POST', ...);

Everything is working nicely now. Also I've create my own WebTestCase class extending the one from Silex so that I don't have to setup the application all the time.

I hope this will help some of you as I didn't find any good help about unit testing with Silex.

Cheers, Maxime

like image 99
maxwell2022 Avatar answered Oct 17 '22 15:10

maxwell2022