使用 FOSUserBundle 以编程方式记录用户以进行功能测试

Posted

技术标签:

【中文标题】使用 FOSUserBundle 以编程方式记录用户以进行功能测试【英文标题】:Logging a User in Programmatically for a Functional Test with FOSUserBundle 【发布时间】:2015-10-16 14:24:46 【问题描述】:

我正在尝试在我对 SF 2.7 和 FOSUserBundle dev-master 的功能测试中以编程方式登录用户。我已经在这个答案中找到了一个很好的参考来通过 SO 登录用户 - Symfony2 - Tests with FOSUserBundle

问题是第二个答案,以编程方式登录用户,不起作用。这是我的代码:

<?php

namespace Test\BackEnd\UserBundle\Controller;

use Test\Shared\CoreBundle\Tests\AbstractControllerTest;
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Loader;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\Tools\SchemaTool;
use FA\BackEnd\UserBundle\DataFixtures\ORM\LoadUserData;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

class DefaultController extends AbstractControllerTest


public function setUp()

    $this->client = static::createClient();

    $container = $this->client->getContainer();

    $doctrine = $container->get('doctrine');
    $em = $doctrine->getManager();
    $schemaTool = new SchemaTool($em);
    $metadata = $em->getMetaDataFactory()->getAllMetadata();

    // Drop and recreate tables for all entities
    $schemaTool->dropSchema($metadata);
    $schemaTool->createSchema($metadata);

    $loader = new Loader();
    $user = new LoadUserData();
    $user->setContainer($container);
    $loader->addFixture($user);

    $purger = new ORMPurger();
    $executor = new ORMExecutor($em, $purger);
    $executor->execute($loader->getFixtures());

    $session = $container->get('session');
    $userManager = $container->get('fos_user.user_manager');

    $user = $userManager->findUserBy(array('username' => 'test'));

    $firewall = 'default';

    $token = new UsernamePasswordToken($user, $user->getPassword(), $firewall, $user->getRoles());
    self::$kernel->getContainer()->get('security.token_storage')->setToken($token);
    $session->set('_security_'.$firewall, serialize($token));
    $session->save();

    $cookie = new Cookie($session->getName(), $session->getId());
    $this->client->getCookieJar()->set($cookie);


public function testProfile()

    //$this->createAuthorizedClient();

    $token = $this->client->getContainer()->get('security.token_storage')->getToken();

    $this->client->request('GET', '/profile/');

    $this->assertEquals(
        200,
        $this->client->getResponse()->getStatusCode(),
        "/profile isn't accessible"
    );



每当我在路由执行之前设置断点时,令牌都会正确返回:

每当我使用控制器 (http://api.symfony.com/2.7/Symfony/Bundle/FrameworkBundle/Controller/Controller.html#method_getUser) 使用的函数 getUser() 时,PHPStorm 都会返回一个空令牌,如下所示:

所以我决定尝试下面的代码来让用户登录,它可以工作。

    $crawler = $this->client->request('GET', '/login');

    $form = $crawler->selectButton('_submit')->form(array(
        '_username'  => 'test',
        '_password'  => 'test123',
    ));

    $this->client->submit($form);
    $this->client->followRedirect(); 

每当我以编程方式登录用户时,我是否没有正确地做某事?会话设置不正确吗?

谢谢!

老鼠

【问题讨论】:

我能看到的唯一与我的做法不同的是您再次调用容器。我想知道它是否出于某种原因超出了范围。尝试在开始时将容器存储在类私有成员中并从那里调用它。 好点。我更正了这一点并添加了: $container->get('security.token_storage')->setToken($token);虽然,这似乎并没有解决它。很有趣。 您是否尝试创建记录用户的 BaseTest?而且您始终可以从登录的用户客户端实例中获取客户端。所以你不需要每次测试都登录。 【参考方案1】:

我用这个:

protected function createAuthorizedClient()
    
     $client = static::createClient();
     $container = $client->getContainer();

     $session = $container->get('session');
     $userManager = $container->get('fos_user.user_manager');
     $loginManager = $container->get('fos_user.security.login_manager');
     $firewallName = $container->getParameter('fos_user.firewall_name');

     $user = $userManager->findUserBy(array('username' => '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()));
     $this->client = $client;

然后在你的测试中:

public function testMiInfo()

    $this->createAuthorizedClient();
    //else..

【讨论】:

你在这里找到的,我猜...advancingusability.wordpress.com/2013/11/15/…

以上是关于使用 FOSUserBundle 以编程方式记录用户以进行功能测试的主要内容,如果未能解决你的问题,请参考以下文章

使用 FosUserBundle 创建管理员用户

如何使用 FOSUserBundle 强制更改密码?

Symfony 4:FOSUserBundle:覆盖控制器

如何明确禁用 FOSUserBundle 中的注册

FOSUserBundle 使用电子邮件登录 (Symfony2)

如何以编程方式记录 PerformanceCounter