如何使用 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 在单元测试中获取当前登录的用户?的主要内容,如果未能解决你的问题,请参考以下文章

Symfony4中的单元测试接口测试

通过单元测试访问 Symfony 2 容器?

如何在 symfony2 功能测试中发出 https 请求?

如何使用 EntityType 字段对 Symfony 4 表单进行单元测试

如何在 Symfony 2 中获取当前路线?

如何在 Symfony 中为使用 queryBuilder 构建的 MongoDB 查询编写单元测试