I am currently working on unit testing my symfony 2.8 based admin area. So I wrote a small basic test for the dashboard: The tests checks that
a) If the user is currently not logged in, there should be a redirect to the login page.
b) If the user is logged in, the dashboard should be shown.
In order to "log in" the user ( = to create an active session) I came up with a small helper function that is based on the respective cookbook article from the symfony documentation: How to Simulate Authentication with a Token in a Functional Test
This however does not seem to work. My initial tests fails. So I have added another request to a dummy controller that only prints out session information. This shows that while the seems to be set correctly, the current user information and the security token storage seem to be incorrect - as I get the default "AnonymousToken" and a null return from the getUser method.
Here is my test code:
<?php
namespace GOC\Bundle\AdminBundle\Tests\Controller;
use FOS\RestBundle\Util\Codes;
use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use GOC\Bundle\FrameworkBundle\Model\ContextInterface;
use GOC\Bundle\FrameworkBundle\Tests\WebTestCase;
class DashboardControllerTest extends WebTestCase
{
const BASE_URL = '';
/**
* @var ContextInterface|null
*/
protected $context;
public static function setUpBeforeClass()
{
$client = static::createClient([
'environment' => 'test',
'debug' => false,
], [
'HTTP_HOST' => 'demo-cms.dev',
]);
$container = $client->getContainer();
$kernel = $container->get('kernel');
$application = new Application($kernel);
$application->setAutoExit(false);
$input = new ArrayInput(array(
'command' => 'doctrine:mongodb:fixtures:load',
));
$output = new NullOutput();
$application->run($input, $output);
}
/**
* Testing whether the backend is not publicly accessible
*/
public function testFirewallRedirect()
{
$client = static::createClient();
$client->request('GET', $this->buildUrl('/admin/dashboard'));
$response = $client->getResponse();
$this->assertTrue($client->getResponse()->isRedirect($this->buildUrl('http://localhost/admin/login')));
$crawler = $client->request('GET', $response->headers->get('location'));
$this->assertEquals(
1,
$crawler->filter('html:contains("Willkommen")')->count()
);
}
/**
* Testing whether the backend is not publicly accessible
*/
public function testFirewallAccess()
{
$client = static::createClient([
'environment' => 'test',
'debug' => false,
], [
'HTTP_HOST' => 'demo-cms.dev',
]);
$this->logIn($client);
$client->request('GET', $this->buildUrl('/admin/dashboard'));
$response = $client->getResponse();
// This fails...
//$this->assertEquals(Codes::HTTP_OK, $response->getStatusCode());
// Debug statements
$client->request('GET', $this->buildUrl('/forgot-password-sent'));
$response = $client->getResponse();
dump($response);
}
/**
* @param Client $client
*/
protected function logIn(Client $client)
{
$container = $client->getContainer();
$repository = $container->get('goc_account.user_manager')->getRepository();
$user = $repository->getUserByUsername('[email protected]', $this->getContext($client));
$firewall = 'main';
$token = new UsernamePasswordToken($user, null, $firewall, $user->getRoles());
$container->get('security.token_storage')->setToken($token);
$session = $container->get('session');
// Saw this somewhere else, makes no difference though
//$session = new Session(new MockArraySessionStorage());
//$session->start();
//$container->set('session', $session);
$session->set('_security_'.$firewall, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$client->getCookieJar()->set($cookie);
}
/**
* @param $url
*
* @return string
*/
protected function buildUrl($url)
{
return $this::BASE_URL . $url;
}
/**
* @param Client $client
*
* @return ContextInterface
*/
protected function getContext(Client $client)
{
if ($this->context) {
return $this->context;
}
$this->context = $client->getContainer()->get('goc_framework.context_manager')->getContextByName('demo');
return $this->context;
}
}
Thanks in advance for any help - it's highly appreciated !