如何在功能测试中使用令牌模拟身份验证时正确设置用户名

时间:2016-11-02 15:26:12

标签: php symfony authentication phpunit functional-testing

我需要编写一个功能测试,以测试每个角色是否都能正确访问这些页面。

为了做到这一点,我simulating authentication with a token,但我稍微编辑了logIn方法,只是使用自定义$username$role和{{1}来调用它}:

$firewall

所以我可以调用它来指定哪些角色应该有假用户:

protected function logIn($username, $role, $firewall)
{
    $session = $this->client->getContainer()->get('session');

    $token = new UsernamePasswordToken($username, null, $firewall, $role);
    $session->set('_security_' . $firewall, serialize($token));
    $session->save();

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

然后我可以测试是否允许用户访问某些路线:

    $this->logIn('my_username@example.com', ['ROLE_USER'], "my_firewall");

这些断言有效,唯一的问题是// check if the access is correctly denied to the ROLE_USER $this->client->request('GET', '/route-not-allowed-to-user'); $this->assertEquals(403, $this->client->getResponse()->getStatusCode()); // check if the access is correctly allowed to the ROLE_USER $this->client->request('GET', '/route-allowed-to-user'); $this->assertNotEquals(403, $this->client->getResponse()->getStatusCode()); 我使用twig输出用户名的视图:

route-allowed-to-user

但它失败了。我收到状态代码{{ app.user.username }}而不是500,并出现以下错误:

  

无法在空变量上访问属性("用户名")

因为200未设置。

如何在使用令牌模拟身份验证时正确设置用户?

2 个答案:

答案 0 :(得分:0)

我认为这是因为您没有通过身份验证过程而只是创建了用户令牌,该用户令牌没有触发存储用户的用户名,角色等的Symfony事件。

我最近通过登录表单,填写数据并发送它来做类似的事情。就像我正在进行真正的登录尝试一样,效果很好。

use Symfony\Component\DependencyInjection\ContainerInterface;

abstract class AuthenticatedTestCase extends KernelTestCase
{
    static protected $client;

    static public function setUpBeforeClass()
    {
        parent::setUpBeforeClass();
        self::$client = static::$kernel->getContainer()->get('test.client');
    }

    static public function login($login, $password)
    {    
        $crawler = self::$client->request('GET', '/test_admin/login');
        $form = $crawler->filter('input[type="submit"]')->form([
            '_username' => $login,
            '_password' => $password,
        ]);

        self::$client->submit($form);

        // Redirect after successful login
        self::assertEquals(302, self::$client->getResponse()->getStatusCode());

        self::$client->followRedirect();

        if (200 === self::$client->getResponse()->getStatusCode()) {
            // Redirected URL is OK
            // ...
        }
    }
}

答案 1 :(得分:0)

我已通过编辑logIn方法解决了以下问题:

protected function logIn($username, $password, $firewall)
{
    $session = $this->client->getContainer()->get('session');
    $authenticationManager = $this->client->getContainer()->get('security.authentication.manager');

    $token = $authenticationManager->authenticate(
        new UsernamePasswordToken(
            $username,
            $password,
            $firewall
        )
    );

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

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

并使用doctrine data fixtures来设置用户和角色。