I am trying to create a unit test for my Silex application. The unit test class looks something like this:
class PageTest extends WebTestCase {
public function createApplication() {
$app = require __DIR__ . '/../../app/app.php';
$app['debug'] = true;
$app['session.storage'] = $app->share(function() {
return new MockArraySessionStorage();
});
$app['session.test'] = true;
unset($app['exception_handler']);
return $app;
}
public function testIndex() {
$client = $this->createClient();
$client->request('GET', '/');
$this->assertTrue($client->getResponse()->isOk());
}
}
and the silex route it is trying to request look something like this:
$app->get('/', function() use($app) {
$user = $app['session']->get('loginUser');
return $app['twig']->render('views/index.twig', array(
'user' => $user,
));
});
This causes an RuntimeException: Failed to start the session because headers have already been sent. in \Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage.php:142 with a backtrace that includes the line from the route with $app['session']->get.
It looks like the output that has occured prior to the session start attempt in NativeSessionStorage is actually the PHPUnit output info, since this is the only output I get before the error message:
PHPUnit 3.7.8 by Sebastian Bergmann.
Configuration read from (PATH)\phpunit.xml
E.......
I am a little confused because this error output from phpunit occur in the output before the actual test method is executed. I don't run any other test methods, so it has to be from this error.
How am I supposed to make PHPUnit work on silex routes that use session variables?
Ok, I found the answer. It seems to be a bug in Silex.
The problem occured when I register a twig extension BEFORE registering the standard FormServiceProvider. It was not caused by anything inside the twig extension, the error still occure if I strip down the whole extension class to nothing but empty methods.
So, registering of twig extensions in the Silex app object should always be done AFTER registering the providers, at least after the FormServiceProvider (Until the bug is fixed).
EDIT after comment below
Ok, I've got the same problem and after an hour browsing the web, I managed to pass tests.
On Silex 2.0-dev, calling
$app['session.test'] = true
from theWebTestCase
class doesn't work at all, it needs to happen in the bootstrap.Many ways to achieve it, here's two of them :
1/ with
phpunit.xml.dist
then in bootstrap
2/ By extending
Silex\Application
so you can pass an environment to the constructorthen in your bootstrap
Hope that helps, cheers !