How to login inside tests to be able to do user-specific actions?
Actually, the authentication must be done like a real user do it. In that case, you have to know the plain password and fill the login form
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class XXX extends WebTestCase {
public function testUserLogin() {
$client = static::createClient();
$crawler = $client->request('GET', '/login');
$form = $crawler->selectButton('_submit')->form(array(
'_username' => 'user',
'_password' => 'pa$$word',
));
$client->submit($form);
$crawler = $client->followRedirect(); // "/" page
// if credentials were correct, you should be logged in and ready to test your app
}
}
The existing answers to this question have been helpful, but none of them solved my problem directly. I'm using Symfony 2.3.
Here is my solution:
<?php
namespace CDE\TestBundle\Base;
use FOS\UserBundle\Model\User;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\BrowserKit\CookieJar;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
class BaseUserTest extends WebTestCase {
protected $client;
protected $container;
protected $storage;
protected $session;
protected $user;
protected $cookieJar;
protected $cookie;
protected $token;
public function __construct() {
$this->client = static::createClient();
$this->container = $this->client->getContainer();
$this->storage = new MockFileSessionStorage(__dir__.'/../../../../app/cache/test/sessions');
$this->session = new Session($this->storage);
}
public function getUserManager() {
return $this->container->get('cde_user.manager.user');
}
public function getSecurityManager() {
return $this->container->get('fos_user.security.login_manager');
}
public function getUser($role = null) {
if (!isset($this->user)) {
$user = $this->getUserManager()->loadByUsername('user');
if (isset($user)) {
$this->user = $user;
} else {
$this->user = $this->getUserManager()->create();
$this->user->setEnabled(true);
$this->user->setUsername('user');
$this->user->setEmail('[email protected]');
$this->user->setPlainPassword('user');
$this->getUserManager()->updatePassword($this->user);
if (isset($role)) {
$this->user->addRole($role);
}
$this->getUserManager()->add($this->user);
}
}
return $this->user;
}
public function logIn(User $user, Response $response) {
$this->session->start();
$this->cookie = new Cookie('MOCKSESSID', $this->storage->getId());
$this->cookieJar = new CookieJar();
$this->cookieJar->set($this->cookie);
$this->token = new UsernamePasswordToken($user, 'user', 'main', $user->getRoles());
$this->session->set('_security_main', serialize($this->token));
$this->getSecurityManager()->loginUser(
$this->container->getParameter('fos_user.firewall_name'),
$user,
$response
);
$this->session->save();
}
public function removeUser(User $user) {
}
}
RestControllerTest.php
<?php
namespace CDE\ContentBundle\Tests\Controller;
use CDE\TestBundle\Base\BaseUserTest;
use Symfony\Component\HttpFoundation\Response;
class RestControllerTest extends BaseUserTest
{
protected $comment;
public function __construct() {
parent::__construct();
$this->logIn($this->getUser('ROLE_ADMIN'), new Response());
}
public function getGalleryManager() {
return $this->container->get('cde_content.manager.gallery');
}
public function getAWSManager() {
return $this->container->get('cde_utility.manager.aws');
}
public function createGallery()
{
// Copy test.jpeg into the web folder
$filename = 'gallery/user-test.jpg';
copy(__DIR__.'/../Mock/test.jpeg', __DIR__.'/../../../../../web/'.$filename);
$this->getAWSManager()->copyGalleryFile($filename);
$gallery = $this->getGalleryManager()->create();
$gallery->setUser($this->getUser());
$gallery->setFilename($filename);
$gallery->setTitle('test gallery');
$gallery->setDescription('test gallery description');
$gallery->setMarked(false);
$this->getGalleryManager()->add($gallery);
$this->assertEquals($gallery->getMarked(), false);
}
public function createComment()
{
$galleries = $this->getGalleryManager()->findByUser($this->getUser());
$gallery = $galleries[0];
$client = static::createClient();
$client->getCookieJar()->set($this->cookie);
// $client = static::createClient(array(), new History(), $cookieJar);
$crawler = $client->request('POST', 'api/createComment/'.$gallery->getId(), array(
'comment' => 'testing testing 123',
'marked' => 'false'
));
$response = $client->getResponse();
$this->comment = json_decode($response->getContent());
$this->assertEquals($this->comment->comment, 'testing testing 123');
$this->assertFalse($this->comment->marked);
$this->assertEquals($response->getStatusCode(), 200);
}
public function getComment()
{
$client = static::createClient();
$crawler = $client->request('GET', 'api/getComment/'.$this->comment->id);
$response = $client->getResponse();
$comment = json_decode($response->getContent());
$this->assertEquals($comment->comment, 'testing testing 123');
$this->assertFalse($comment->marked);
$this->assertEquals($response->getStatusCode(), 200);
}
public function updateComment()
{
$client = static::createClient();
$crawler = $client->request('GET', 'api/updateComment');
}
public function deleteComment()
{
$client = static::createClient();
$crawler = $client->request('DELETE', 'api/deleteComment');
}
public function getComments()
{
$client = static::createClient();
$crawler = $client->request('GET', 'api/getComments');
}
public function getGalleries()
{
$client = static::createClient();
$crawler = $client->request('GET', 'api/getGalleries');
}
public function removeGallery() {
$galleries = $this->getGalleryManager()->findByUser($this->getUser());
foreach ($galleries as $gallery) {
$this->getGalleryManager()->remove($gallery);
}
}
public function testComments() {
$this->createGallery();
$this->createComment();
$this->getComment();
$this->updateComment();
$this->deleteComment();
$this->getComments();
$this->getGalleries();
$this->removeGallery();
}
}
The code includes a base test class (BaseUserTest.php
) that can be extended to easily log in users.
I've also included an example of how to use the base class in an example test (RestControllerTest.php
). Notice this code block in RestControllerTest.php:
$client = static::createClient();
$client->getCookieJar()->set($this->cookie);
The idea behind BaseUserTest is that it can create it's own session, populate the session with the user, and then save the session to the file system using MockFileSessionStorage.
The tests themselves must then set the cookie on the client.
I know it is too late.. But in case someone needs this, I managed to logg a user in my unit test like this:
1- First Define a class which will give you access to services:
<?php
namespace Tests;
class ContainerAwareUnitTestCase extends \PHPUnit_Framework_TestCase
{
protected static $kernel;
protected static $container;
public static function setUpBeforeClass()
{
self::$kernel = new \AppKernel('dev', true);
self::$kernel->boot();
self::$container = self::$kernel->getContainer();
}
public function get($serviceId)
{
return self::$kernel->getContainer()->get($serviceId);
}
}
2- Then declare a test as follow:
<?php
namespace Tests\Menu;
use Tests\ContainerAwareUnitTestCase;
use UserBundle\Entity\User;
use FOS\UserBundle\Security\UserProvider;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\Request;
use Menu\MenuBuilder;
class MenuBuilderTest extends ContainerAwareUnitTestCase
{
public function provider()
{
return array(array('/'));
}
/**
* @dataProvider provider
*/
public function testNoAuth($uri)
{
/* @var $securityContext SecurityContext */
$securityContext = $this->get('security.context');
$userProvider = $this->get('fos_user.user_provider.username');
$user = $userProvider->loadUserByUsername('alex');
$token = new UsernamePasswordToken($user, null, 'main', array('ROLE_USER'));
$securityContext->setToken($token);
/* @var $menuBuilder MenuBuilder */
$menuBuilder = $this->get('event_flow_analyser.menu_builder');
$this->assertNotNull($menuBuilder);
$request = new Request();
$request->attributes->set('projectName', 'ucs');
$menu = $menuBuilder->createMainMenu($request);
$this->assertNotNull($menu);
$this->assertNotNull($menu->getChild('Home'));
$this->assertNotNull($menu->getChild('Profile'));
$this->assertEquals(null, $menu->getChild('Projects'));
}
}
This a complete exemple to test menuBuilder creation, but although a little out of scope, that extract should answer your need:
$securityContext = $this->get('security.context');
$userProvider = $this->get('fos_user.user_provider.username');
$user = $userProvider->loadUserByUsername('alex');
$token = new UsernamePasswordToken($user, null, 'main', array('ROLE_USER'));
$securityContext->setToken($token);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With