Symfony PHPUnit 测试不验证用户

Posted

技术标签:

【中文标题】Symfony PHPUnit 测试不验证用户【英文标题】:Symfony PHPUnit tests don't authenticate user 【发布时间】:2021-12-02 00:20:35 【问题描述】:

我有一个 Symfony 4.4 项目。登录、身份验证和授权在 Web 上工作正常。

为了在单元测试中模拟身份验证,我使用Symfony's example。

...但这不起作用。用户未在单元测试中进行身份验证。我收到未经授权的错误消息“需要完全身份验证才能访问此资源。”

我的测试:


namespace App\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;

class DefaultControllerTest extends WebTestCase

    private $client = null;

    public function setUp()
    
        $this->client = static::createClient();
    

    public function testJsonUserEndpoint()
    
        $this->logIn();
        $crawler = $this->client->request('GET', '/json/user');

        $this->assertNotContains('invalid_credentials', $this->client->getResponse()->getContent());
    

    private function logIn()
    
        $user = self::$container->get(EntityManagerInterface::class)->getRepository(User::class)->findOneByMail('test106@test.com');

        $session = $this->client->getContainer()->get('session');

        $firewallName = 'main';
        $firewallContext = 'main';

        $token = new PostAuthenticationGuardToken($user, $firewallName, ['ROLE_USER']);
        $session->set('_security_'.$firewallContext, serialize($token));
        $session->save();

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

我的防火墙:

        main:
            anonymous:
                secret: '%env(APP_SECRET)%'
            remember_me:
                always_remember_me: true
                secret: '%env(APP_SECRET)%'
            provider: session_user_provider
            guard:
                authenticators:
                    - App\Security\Authenticator\LoginAuthenticator
                    - App\Security\Authenticator\MobileBridgeAuthenticator
                    - App\Security\Authenticator\BearerTokenAuthenticator
                    - App\Security\Authenticator\HashAuthenticator
                    - App\Security\Authenticator\ClientAuthenticator
                entry_point: App\Security\Authenticator\LoginAuthenticator

            logout:
                path: execute_logout
                target: render_login

单元测试失败:

1) App\Tests\Controller\DefaultControllerTest::testJsonUserEndpoint
Failed asserting that '"status":"invalid_credentials","errors":["Invalid Credentials"],"debug":"Full authentication is required to access this resource.","error":"Unauthorized"' does not contain "invalid_credentials".

如何在不使用登录表单的情况下对单元测试中的用户进行身份验证?

【问题讨论】:

【参考方案1】:

问题是我没有将角色与用户一起存储在数据库中——它们被添加到我的身份验证器中——并且将角色传递给PostAuthenticationGuardToken 是不够的。我还必须将它们添加到令牌中的用户:

$user->setRoles(['ROLE_USER']);
$token = new PostAuthenticationGuardToken($session_user, $firewallName, ['ROLE_USER']);

其实,只要是一个数组,Token 的角色是什么都没关系:

$user->setRoles(['ROLE_USER']);
$token = new PostAuthenticationGuardToken($session_user, $firewallName, []);

【讨论】:

以上是关于Symfony PHPUnit 测试不验证用户的主要内容,如果未能解决你的问题,请参考以下文章

在 phpunit 测试中覆盖 symfony TokenAuthenticator

Symfony4中的单元测试接口测试

Symfony Doctrine 关系在 PhpUnit 测试中为空

运行 PHPUnit 测试时,容器参数在 Symfony 5 服务中不可用/注入

用 phpunit 模拟 symfony 安全,返回空值而不是布尔值(不使用预言)

Symfony:如何正确地从phpunit / phpunit切换到phpunit桥