4
votes

I'm creating an application in Silex with unit tests.

Running unit tests works fine against the regular session handler:

$app->register(new Silex\Provider\SessionServiceProvider(), array(
    'session.storage.options' => array(
        'cookie_lifetime' => 1209600, // 2 weeks
    ),
));

and setting this flag in my unit tests:

$this->app['session.test'] = true;

If I don't set that session.test flag, my unit tests throw a headers already sent error and all fail. With it on, my tests run well.

The issue is I am attempting to use the flashBag feature (session info that lasts only until first request then get removed):

$foo = $app['session']->getFlashBag()->all();

The flashBag does not seem to respect the session.test flag, and attempts to send headers, which cause all my unit tests to fail:

24) Yumilicious\UnitTests\Validator\PersonAccountTest::setConstraintsPassesWithMinimumAttributes RuntimeException: Failed to start the session because headers have already been sent.

/webroot/yumilicious/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php:142 /webroot/yumilicious/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php:262 /webroot/yumilicious/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Session/Session.php:240 /webroot/yumilicious/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Session/Session.php:250 /webroot/yumilicious/src/app.php:38 /webroot/yumilicious/tests/Yumilicious/UnitTests/Base.php:13 /webroot/yumilicious/vendor/silex/silex/src/Silex/WebTestCase.php:34 /webroot/yumilicious/vendor/EHER/PHPUnit/src/phpunit/phpunit.php:46 /webroot/yumilicious/vendor/EHER/PHPUnit/bin/phpunit:5

I've narrowed it down to this bit of code: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php#L259

Specifically, line 262. Commenting out that single line allows my tests to work properly and all pass green.

I've searched quite a bit to get this to work, but am not having any luck. I think it's because the flashBag stuff is new (https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Session/Session.php#L305) and the old methods are being deprecated.

Any suggestions on getting my unit tests to work would be awesome.

3
I faced the same problem today on Silex 2.0-dev.<br> But none of the answers on stack did the trick.<br> <br> I came up with a possible answer here : stackoverflow.com/a/34005216/4323472Heah

3 Answers

4
votes

For testing you need to replace the session.storage service with an instance of MockArraySessionStorage:

use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;

$app['session.storage'] = new MockArraySessionStorage();

This is because the native one tries to send a cookie via header which of course fails in a test environment.

EDIT: There is now a session.test parameter that you should set to true. That will automatically make the session use a mock storage.

3
votes

I had this happen too, if i am not mistaking i fixed by having my unittests run via a different environment, wich has

framework:
    test: ~
    session:
        storage_id: session.storage.mock_file

set in the config_test.yml

0
votes

I came across similar problem today and temp fix would be to comment out block of code in

\Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage

in start() method

   /*
   if (ini_get('session.use_cookies')  && headers_sent()) {
       throw new \RuntimeException('Failed to start the session because headers have already been sent.');
   }
   */

This solution keeps tests "green" and from looks of it the application session functionality as is.