I have been stuck for some time on an error to do my functional tests with symfony 3.4.
My app run a custom GuardAuthenticator for authenticate my users within CAS authentication. This is just for explain the context. In my tests, I don't want to use it, I want to use a specific authentication system.
I wrote functional tests. I started my test environment with the following :
# app/config/config_test.yml
imports:
- { resource: config_dev.yml }
framework:
test: ~
session:
storage_id: session.storage.mock_file
name: MOCKSESSION
profiler:
collect: false
According to the official Symfony doc, I extends symfony WebTestCase for set a specific authentication token for my tests How to Simulate HTTP Authentication in a Functional Test
namespace Test\AppBunble\WebTestCase;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as SfTestCase;
class WebTestCase extends SfTestCase
{
/**
*
* {@inheritDoc}
* @see \PHPUnit_Framework_TestCase::setUp()
*/
public function setUp()
{
$this->client = static::createClient();
$this->container = $this->client->getContainer();
$this->entityManager = $this->container->get('doctrine.orm.entity_manager');
parent::setUp();
}
public function logInAs($username)
{
$user = $this->entityManager->getRepository(User::class)->loadUserByUsername($username);
$session = $this->client->getContainer()->get('session');
$token = new PostAuthenticationGuardToken($user, 'main', $user->getRoles());
$session->set('_security_main', serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
}
Finally, I wrote my (simple) test :
namespace Tests\AppBundle\Controller;
use Tests\AppBundle\WebTestCase;
class DefaultControllerTest extends WebTestCase
{
public function testIndex()
{
$this->logInAs('admin');
$crawler = $this->client->request('GET', '/');
$this->assertTrue($client->getResponse()->isSuccessful(), 'response status is 2xx');
}
}
I ran phpunit :
$ ./vendor/bin/simple-phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
Testing app Test Suite
<br />
<b>Error</b>: <font color="FF0000"><b>Internal script failure</b><br />
For debugging, I modified my test :
public function testIndex()
{
$this->logInAs('admin');
//$crawler = $this->client->request('GET', '/');
//$this->assertTrue($client->getResponse()->isSuccessful(), 'response status is 2xx');
}
I ran phpunit :
./vendor/bin/simple-phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
Testing app Test Suite
. 1 / 1 (100%)
Time: 797 ms, Memory: 27.75MB
OK (1 test, 0 assertions)
After lots of tests I found when I call in my test :
$this->client->request('GET', '/')
It crash.
UPDATE : another test.
If I ran this :
public function testIndex()
{
$this->logInAs('admin');
$token = $this->client->getContainer()->get('security.token_storage');
var_dump($token->getToken());
//$crawler = $this->client->request('GET', '/');
//$this->assertTrue($client->getResponse()->isSuccessful(), 'response status is 2xx');
}
It return me NULL
... no token.
UPDATE 2
I dove into the code to go back to the point where symfony stops. It's in the doDispatch
method of Symfony\Component\EventDispatcher\EventDispatcher
class.
It trigger the listeners on the `kernel.event' event. And when it trigger the listener named "Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener" => "internal script failure".
UPDATE 3 If I compare dev.log (which represents log when I run app in browser), I have this log on a request :
[2020-10-23 13:55:56] request.INFO: Matched route "app_homepage". {"route":"app_homepage","route_parameters":{"_controller":"AppBundle\\Controller\\DefaultController::indexAction","_route":"app_homepage"},"request_uri":"http://localhost:8180/","method":"GET"} []
[2020-10-23 13:55:56] security.DEBUG: Read existing security token from the session. {"key":"_security_main","token_class":"Symfony\\Component\\Security\\Guard\\Token\\PostAuthenticationGuardToken"} []
[2020-10-23 13:55:56] doctrine.DEBUG: SELECT [...]
[2020-10-23 13:55:56] security.DEBUG: User was reloaded from a user provider. [...]
But when I run $this->client->request('GET', '/')
, my test.log show :
[2020-10-23 13:55:56] request.INFO: Matched route "app_homepage". {"route":"app_homepage","route_parameters":{"_controller":"AppBundle\\Controller\\DefaultController::indexAction","_route":"app_homepage"},"request_uri":"http://localhost","method":"GET"} []
No trace from security.
UPDATE 4 : another test
I ran this test :
public function testIndex()
{
$crawler = $this->client->request('GET', '/stackTest');
$this->assertTrue($this->client->getResponse()->isSuccessful(), 'response status is 2xx');
}
It's a page with this configuration in security.yml
firewalls:
stack:
pattern: ^/stackTest
security: false
... and the test works!
./vendor/bin/simple-phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
Testing app Test Suite
. 1 / 1 (100%)
Time: 1.08 seconds, Memory: 36.50MB
OK (1 test, 1 assertion)
$this->client->request('GET', '/')
is[2020-10-23 13:21:01] request.INFO: Matched route "app_homepage". {"route":"app_homepage","route_parameters":{"_controller":"AppBundle\\Controller\\DefaultController::indexAction","_route":"app_homepage"},"request_uri":"http://localhost/","method":"GET"} []
. It's weird as if symfony is stopping somewhere, hence the "internal servererror" message. – artscorestudio\Serializable
, it could be that not all the necessary properties serializing/unserializing properly, which used to compare if user changed. Try to debugSymfony\Component\Security\Core\Authentication\Token\AbstractToken::hasUserChanged()
. But that's weird that it fails with error, I guess problem somewhere else. – vstelmakh