首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Symfony 2.8 WebTestCase:无法创建已登录的会话

Symfony 2.8 WebTestCase:无法创建已登录的会话
EN

Stack Overflow用户
提问于 2016-11-24 17:31:25
回答 1查看 398关注 0票数 1

我目前正在对基于symfony 2.8的管理区域进行单元测试。因此,我为仪表板编写了一个小型的基本测试:测试检查

a)如果用户当前未登录,则应重定向到登录页面。

b)如果用户已登录,则应显示仪表板。

为了“登录”用户(=创建活动会话),我想出了一个小帮手函数,它基于symfony文档中相应的食谱文章:How to Simulate Authentication with a Token in a Functional Test

然而,这似乎不起作用。我的初始测试失败了。因此,我向一个仅打印会话信息的虚拟控制器添加了另一个请求。这表明虽然似乎设置正确,但当前用户信息和安全令牌存储似乎不正确-因为我从getUser方法得到默认的"AnonymousToken“和null返回。

下面是我的测试代码:

代码语言:javascript
复制
<?php

namespace GOC\Bundle\AdminBundle\Tests\Controller;

use FOS\RestBundle\Util\Codes;

use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

use GOC\Bundle\FrameworkBundle\Model\ContextInterface;
use GOC\Bundle\FrameworkBundle\Tests\WebTestCase;

class DashboardControllerTest extends WebTestCase
{
    const BASE_URL = '';

    /**
     * @var ContextInterface|null
     */
    protected $context;

    public static function setUpBeforeClass()
    {
        $client = static::createClient([
            'environment' => 'test',
            'debug'       => false,
        ], [
            'HTTP_HOST' => 'demo-cms.dev',
        ]);

        $container = $client->getContainer();
        $kernel    = $container->get('kernel');

        $application = new Application($kernel);
        $application->setAutoExit(false);

        $input = new ArrayInput(array(
            'command' => 'doctrine:mongodb:fixtures:load',
        ));
        $output = new NullOutput();
        $application->run($input, $output);
    }

    /**
     * Testing whether the backend is not publicly accessible
     */
    public function testFirewallRedirect()
    {
        $client = static::createClient();

        $client->request('GET', $this->buildUrl('/admin/dashboard'));
        $response = $client->getResponse();

        $this->assertTrue($client->getResponse()->isRedirect($this->buildUrl('http://localhost/admin/login')));

        $crawler  = $client->request('GET', $response->headers->get('location'));

        $this->assertEquals(
            1,
            $crawler->filter('html:contains("Willkommen")')->count()
        );
    }

    /**
     * Testing whether the backend is not publicly accessible
     */
    public function testFirewallAccess()
    {
        $client = static::createClient([
            'environment' => 'test',
            'debug'       => false,
        ], [
            'HTTP_HOST' => 'demo-cms.dev',
        ]);

        $this->logIn($client);

        $client->request('GET', $this->buildUrl('/admin/dashboard'));
        $response = $client->getResponse();

        // This fails...
        //$this->assertEquals(Codes::HTTP_OK, $response->getStatusCode());

        // Debug statements
        $client->request('GET', $this->buildUrl('/forgot-password-sent'));
        $response = $client->getResponse();
        dump($response);
    }

    /**
     * @param Client $client
     */
    protected function logIn(Client $client)
    {
        $container = $client->getContainer();

        $repository = $container->get('goc_account.user_manager')->getRepository();
        $user       = $repository->getUserByUsername('admin@gardenofconcepts.com', $this->getContext($client));

        $firewall = 'main';
        $token    = new UsernamePasswordToken($user, null, $firewall, $user->getRoles());

        $container->get('security.token_storage')->setToken($token);
        $session = $container->get('session');

        // Saw this somewhere else, makes no difference though
        //$session = new Session(new MockArraySessionStorage());
        //$session->start();
        //$container->set('session', $session);


        $session->set('_security_'.$firewall, serialize($token));
        $session->save();

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

    /**
     * @param $url
     *
     * @return string
     */
    protected function buildUrl($url)
    {
        return $this::BASE_URL . $url;
    }

    /**
     * @param Client $client
     *
     * @return ContextInterface
     */
    protected function getContext(Client $client)
    {
        if ($this->context) {

            return $this->context;
        }

        $this->context = $client->getContainer()->get('goc_framework.context_manager')->getContextByName('demo');

        return $this->context;
    }
}

提前感谢您的帮助--非常感谢!

EN

回答 1

Stack Overflow用户

发布于 2016-11-24 21:27:11

我们不是试图模拟令牌,而是使用以下函数创建一个令牌(可能适合您的情况):

代码语言:javascript
复制
protected function createAuthenticatedClient($username, $password)
{
    $client = static::createClient();
    $client->request(
        'POST',
        '/api/v1/login_check',
        array(
            'username' => $username,
            'password' => $password,
        )
    );

    $data = json_decode($client->getResponse()->getContent(), true);

    $client = static::createClient();
    $client->setServerParameter('HTTP_Authorization', sprintf('Bearer %s', $data['token']));

    return $client;
}

在像这样使用之后

代码语言:javascript
复制
 $client = $this->createAuthenticatedClient('user', 'password');

每个发送的请求都将与我们的实际持票人联系在一起。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40782516

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档