如何使用 Symfony 2 在单元测试中获取当前登录的用户?
Posted
技术标签:
【中文标题】如何使用 Symfony 2 在单元测试中获取当前登录的用户?【英文标题】:How to get the current logged user in unit test with Symfony 2? 【发布时间】:2015-03-03 04:23:11 【问题描述】:我有这个单元测试:
class ProjectControllerTest extends WebTestCase
private $client = null;
private $projectName = null;
/**
* @var \Doctrine\ORM\EntityManager
*/
private $em;
public function setUp()
$kernel = static::createKernel();
$kernel->boot();
$this->client = $this->createAuthorizeClient($kernel);
$this->em = $kernel->getContainer()->get('doctrine.orm.entity_manager');
public function testProjectNameEdition()
$project = new Project();
$project
->setName(uniqid())
->setComment('test')
;
$this->em->persist($project);
$this->em->flush();
$crawler = $this->client->request('GET', '/project/' . $project->getId() . '/edit');
$form = $crawler->selectButton('codex_gui_project_submit')->form();
$form['codex_gui_project[name]'] = $this->projectName . '1';
$this->client->submit($form);
$editProject = $this->em->getRepository('DatawordsCodexGuiBundle:Project')->findOneByName($oldProjectName . '1');
$this->assertEquals($this->projectName . '1', $editProject->getName());
public function createAuthorizeClient($kernel)
$client = static::createClient();
$container = $kernel->getContainer();
$session = $container->get('session');
$user = $kernel
->getContainer()->get('doctrine')
->getRepository('DatawordsCodexCoreBundle:User')
->findOneByUsername('Nico')
;
$token = new UsernamePasswordToken($user, $user->getUserName(), 'main', $user->getRoles());
$session->set('_security_main', serialize($token));
$session->save();
$client->getCookieJar()->set(new Cookie($session->getName(), $session->getId()));
return $client;
然后当新实体被持久化时,当前用户正在进入ProjectListenner:
class ProjectListener
protected $container;
public function __construct(ContainerInterface $container)
$this->container = $container;
/**
* Prepersist a creation of project
*
* @param \Doctrine\ORM\Event\LifecycleEventArgs $args
*/
public function prePersist(LifecycleEventArgs $args)
$entity = $args->getEntity();
if ($entity instanceof Project)
// Save the user and the created date
$usr = $this->container->get('security.context')->getToken()->getUser();
$entity->setCreated(new \DateTime());
$entity->setCreator($usr);
所以这个错误发生在我运行测试时:
...PHP 致命错误:在非对象上调用成员函数 getUser() /var/www/codex_gui/vendor/acme/foo/Acme/foo/fooBundle/Listener/ProjectListener.php 在第 32 行
【问题讨论】:
看来您在测试用例中测试的逻辑太多了。你真的应该努力在每个测试中用一种方法测试一个用例。您可能还想研究模拟您的依赖项(其他对象、服务调用等)。您得到的最终结果是一个极其脆弱的测试用例,如果被破坏,可能需要大量调试才能找到根本原因。 感谢您的建议。我想我也需要嘲笑一些依赖。但我没有找到适合我的案例的例子。 【参考方案1】:您在创建用户和登录时遇到了一些错误。我不知道您为什么要进行如此多的static::
调用,但您应该只在创建客户端时这样做。例如:
private $container;
public function setUp()
$this->client = static::createClient();
$this->container = $this->client->getContainer();
$this->em = $this->container->get('doctrine.orm.entity_manager');
$this->createAuthorizeClient();
您不需要将$this->client
传递给您的createAuthorizeClient()
函数。它应该看起来更像
public function createAuthorizeClient()
$session = $this->container->get('session');
$user = $this->em->getRepository('AcmeFooBundle:User')
->findOneByUsername('Nico');
// rest of the class here
可能还有其他问题,但这只是您可以做的一组基本操作。查看 http://symfony.com/doc/current/cookbook/testing/simulating_authentication.html 以及他们如何为功能测试创建用户。
【讨论】:
感谢您提供这些提示。我按照您的指示编辑了我的代码。我也读了你的链接。 但问题仍然存在,当我运行单元测试时,我无法在“ProjectListenner”中获取当前用户。 你没有按照我说的去做。您不需要显式引导内核或将其传递给您的createAuthorizeClient
函数。试试我的建议。
哦!你对不对,复制/粘贴错误。我再次编辑。
实际上,当我通过使用爬虫创建项目来替换以编程方式创建项目时,它正在工作。问题还是一样,当项目创建来自单元测试时,我不明白如何在项目监听器中获取当前用户。抱歉,我不明白如何应用您的指示。你有例子吗?
是的,这个例子已经在我的回答中...尝试更改您的代码以匹配我输入的内容以上是关于如何使用 Symfony 2 在单元测试中获取当前登录的用户?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 symfony2 功能测试中发出 https 请求?