Reputation: 16515
I am trying to test a Service which preprocessed a form and finally saves it. Within the creating of that form:
$this->container->get('security.token_storage')->getToken()->getUser();
is called to get currently logged in user as a default value for a field.
Right now I am having this (extending Symfony\Bundle\FrameworkBundle\Test\WebTestCase
):
private $pages;
private $formFactory;
protected function setUp()
{
self::bootKernel();
$client = self::$kernel->getContainer()->get('test.client');
$client->setServerParameters([
'HTTP_HOST' => 'ajax.localhost.dev:10190',
'CONTENT_TYPE' => 'application/json',
'HTTP_X-Requested-With' => 'XMLHttpRequest',
'HTTP_USER_AGENT' => 'Symfony/2.0',
'PHP_AUTH_USER' => 'root',
'PHP_AUTH_PW' => '[email protected]'
]);
$this->pages = self::$kernel->getContainer()->get('app.pages');
$this->formFactory = self::$kernel->getContainer()->get('form.factory');
}
public function testNewPage() {
$page = new Page();
//shortened
$form = $this->formFactory->create(PageType::class, $page);
}
But that gives me the error:
Call to a member function getUser() on null
What shows that there is no security token.
How can I come over that?
UPDATE
Thanks to the comments of @LBA I tried that code, with no luck:
$session = self::$kernel->getContainer()->get('session');
$token = new UsernamePasswordToken('root', 'root', 'main', ['ROLE_USER', 'ROLE_ROOT']);
$session->set('_security_main', serialize($token));
$session->save();
The part with setting a Cookie as described here is missing, since the $kernel
has no method getCookieJar()
Upvotes: 1
Views: 51
Reputation: 16515
I could finally make it work like so:
protected function setUp()
{
self::bootKernel();
$root = new User();
$root->setUsername('root');
$root->setPassword('root');
$root->setEmail('[email protected]');
$token = new UsernamePasswordToken($root, null, 'main', ['ROLE_USER', 'ROLE_ROOT']);
self::$kernel->getContainer()
->get('security.token_storage')
->setToken($token);
$this->pages = self::$kernel->getContainer()->get('app.pages');
$this->formFactory = self::$kernel->getContainer()->get('form.factory');
}
BUT BUT BUT Even if it is possible to solve that problem, the real issue in this case is, to have that $this->container->get('security.token_storage')->getToken()->getUser();
call with the Form, since this breaks the form in a test case. The pattern to prevent such a thing from happening is dependency injection, what I have missed to apply on the form type.
So the better solution would be (in the Form extending AbstractType):
public function configureOptions(OptionsResolver $resolver)
{
$this->setDefined(['user]);
}
And finally create the form like so (in Controller or TestCase)
Within a UnitTest:
$user = new User();
and in the controller:
$user = $this->container->get('security.token_storage')->getToken()->getUser();
$form = $this->formFactory->create(TheFormType::class,
<some data object>,
['user' => $user]);
Upvotes: 1