繁体   English   中英

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

[英]Symfony 2.8 WebTestCase: Cannot create logged-in session

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

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

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

为了“登录”用户(=创建活动会话),我想出了一个小帮助函数,该函数基于symfony文档中的相应菜谱文章: 如何在功能测试中使用令牌模拟身份验证

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

这是我的测试代码:

<?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;
    }
}

在此先感谢您的帮助 - 非常感谢!

我们不是试图模拟令牌,而是实际创建一个具有以下功能(可能适合您的情况):

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;
}

使用后喜欢这样

 $client = $this->createAuthenticatedClient('user', 'password');

发送的每个请求都将附在我们的实际承载上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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