简体   繁体   中英

Symfony2 - Tests with FOSUserBundle

i would write a test for Symfony2 with FOSUserBundle.

At the moment i tried some ways and no one works.

I need a function like "createAuthClient".

Here is my basic class. I post it because you could understand my problem better.

<?php
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\BrowserKit\Cookie;

class WebTestMain extends WebTestCase
{
    protected static $container;

    static protected function createClient(array $options = array(), array $server = array())
    {
        $client = parent::createClient($options, $server);

        self::$container = self::$kernel->getContainer();

        return $client;
    }

    static function createAuthClient(array $options = array(), array $server = array())
    {
        // see lines below with my tries
    }
}

First try:

if(static::$kernel === null)
{
    static::$kernel = static::createKernel($options);
    static::$kernel->boot();
}
if(static::$container === null)
{
    self::$container = self::$kernel->getContainer();
}

$parameters = self::$container->getParameter('test');
$server = array_merge(array('HTTP_HOST' => $parameters['host'], 'HTTP_USER_AGENT' => $parameters['useragent']), $server);

$client = self::createClient($options, $server);

$userProvider = self::$container->get('fos_user.user_manager');
$user = $userProvider->findUserBy(array('id' => 1));
$client->getCookieJar()->set(new Cookie('MOCKSESSID', true));
$session = self::$kernel->getContainer()->get('session');
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$client->getContainer()->get('security.context')->setToken($token);
$session->set('_security_main', serialize($token));

return $client;

Then i searched and searched... My second try.

if(static::$kernel === null)
{
    static::$kernel = static::createKernel($options);
    static::$kernel->boot();
}
if(static::$container === null)
{
    self::$container = self::$kernel->getContainer();
}

$parameters = self::$container->getParameter('test');
$server = array_merge(
    array(
        'HTTP_HOST' => $parameters['host'],
        'HTTP_USER_AGENT' => $parameters['useragent'],
        'PHP_AUTH_USER' => 'admin',
        'PHP_AUTH_PW'   => 'admin'
    ),
    $server
);
$client = static::createClient(array(), array());
$client->followRedirects();
return $client;

And here is my last try before i post this question...

$client = self::createClient($options, $server);

$parameters = self::$container->getParameter('test');
$server = array_merge(
    array(
        'HTTP_HOST' => $parameters['host'],
        'HTTP_USER_AGENT' => $parameters['useragent']
    ),
    $server
);

$client->setServerParameters($server);

$usermanager = self::$container->get('fos_user.user_manager');
$testuser = $usermanager->createUser();
$testuser->setUsername('test');
$testuser->setEmail('test@mail.org');
$testuser->setPlainPassword('test');
$usermanager->updateUser($testuser);

return $client;

Thank you in Advance.

The best way I have found to test with an authenticated user is to just visit your login page and submit the form with user name and password you have loaded from a fixture. This may seem slow and cumbersome but will test what the user will actually do. You can even create your own method to make using it quick and easy.

public function doLogin($username, $password) {
   $crawler = $this->client->request('GET', '/login');
   $form = $crawler->selectButton('_submit')->form(array(
       '_username'  => $username,
       '_password'  => $password,
       ));     
   $this->client->submit($form);

   $this->assertTrue($this->client->getResponse()->isRedirect());

   $crawler = $this->client->followRedirect();
}

Create an AbstractControllerTest and create an authorized client on setUp() as follow:

<?php
// ...
use Symfony\Component\BrowserKit\Cookie;

abstract class AbstractControllerTest extends WebTestCase
{
    /**
     * @var Client
     */
    protected $client = null;


    public function setUp()
    {
        $this->client = $this->createAuthorizedClient();
    }

    /**
     * @return Client
     */
    protected function createAuthorizedClient()
    {
        $client = static::createClient();
        $container = $client->getContainer();

        $session = $container->get('session');
        /** @var $userManager \FOS\UserBundle\Doctrine\UserManager */
        $userManager = $container->get('fos_user.user_manager');
        /** @var $loginManager \FOS\UserBundle\Security\LoginManager */
        $loginManager = $container->get('fos_user.security.login_manager');
        $firewallName = $container->getParameter('fos_user.firewall_name');

        $user = $userManager->findUserBy(array('username' => 'REPLACE_WITH_YOUR_TEST_USERNAME'));
        $loginManager->loginUser($firewallName, $user);

        // save the login token into the session and put it in a cookie
        $container->get('session')->set('_security_' . $firewallName,
            serialize($container->get('security.context')->getToken()));
        $container->get('session')->save();
        $client->getCookieJar()->set(new Cookie($session->getName(), $session->getId()));

        return $client;
    }
} 

NOTE: Please, replace the username with your test username.

Then, extends the AbstractControllerTest and use the global $client to make requests as follow:

class ControllerTest extends AbstractControllerTest
{
    public function testIndexAction()
    {
        $crawler = $this->client->request('GET', '/admin/');

        $this->assertEquals(
            Response::HTTP_OK,
            $this->client->getResponse()->getStatusCode()
        );
    }
}

This method tested and works fine

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM