在Symfony单元测试期间无法获取用户名

在Symfony单元测试期间无法获取用户名,symfony,unit-testing,authentication,doctrine,Symfony,Unit Testing,Authentication,Doctrine,在Symfony 3 with Doctrine中,我试图在数据库中设置一个last updated by列,每当将更改保存到表中时,该列将自动设置为登录用户的用户名 我使用一个EventSubscriber来实现这一点,当我真正使用系统时,它可以工作,但是当我运行单元测试时,它认为没有用户登录 我遵循的说明建议了两种方法——使用基本身份验证或设置令牌。这两种方法都允许测试在用户经过身份验证的情况下运行,但它们都不允许我检索登录用户的用户名,因此我无法测试是否正确设置了last updated

在Symfony 3 with Doctrine中,我试图在数据库中设置一个last updated by列,每当将更改保存到表中时,该列将自动设置为登录用户的用户名

我使用一个EventSubscriber来实现这一点,当我真正使用系统时,它可以工作,但是当我运行单元测试时,它认为没有用户登录

我遵循的说明建议了两种方法——使用基本身份验证或设置令牌。这两种方法都允许测试在用户经过身份验证的情况下运行,但它们都不允许我检索登录用户的用户名,因此我无法测试是否正确设置了last updated by列

我做错了什么?是否有其他方法可以检索EventSubscriber中登录用户的用户名

这是我的EventSubscriber实现,它适用于实际请求,但在测试运行时返回空令牌:

class BaseEntitySubscriber implements EventSubscriber {
    public function getSubscribedEvents() {
        return array('prePersist');
    }

    public function prePersist(LifecycleEventArgs $args) {
        $em = $args->getEntityManager();
        $token = $this->ts->getToken(); // returns null during tests
        $username = $token ? $token->getUsername() : null;
        if ($username === null) throw new \Exception("User is not logged in!");
        $entity = $args->getEntity();
        $entity->setLastUpdateBy($username);
    }
}

# services.yml
AppBundle\EventListener\BaseEntitySubscriber:
    tags:
        - { name: doctrine.event_subscriber, connection: default }
    arguments: [ "@security.token_storage" ]
编辑:@dbrumann测试代码如下所示:大致

public function testEditLookup()
{
    $idLookup = $this->getFixtureId('lookup.example');

    // Get the existing one first so we know if it changes later.
    $crawler = $this->client->request('GET', "/lookup/$idLookup");
    $lookup = $this->decodeSymfonyJSON($this->client->getResponse());

    $this->assertEquals('Old title', $lookup['title']);
    $this->assertEquals('system', $lookup['last_update_by']);
    $this->assertEquals('Example', $lookup['detail']);

    // Make the change.
    $crawler = $this->client->request('PATCH',
        "/lookup/$idLookup",
        array('title' => 'New title')
    );
    $this->checkSymfonyError($this->client->getResponse());

    // Retrieve it again to confirm it is now different.
    $crawler = $this->client->request('GET', "/lookup/$idLookup");
    $lookup = $this->decodeSymfonyJSON($this->client->getResponse());

    $this->assertEquals('New title', $lookup['title']);
    $this->assertEquals('testuser', $lookup['last_update_by']);
    // Make sure this hasn't changed.
    $this->assertEquals('Example', $lookup['detail']);
}

我想我已经解决了这个问题。事实证明——假设我以正确的方式检索用户——您需要自己设置一个令牌:

$user = 'testuser';
$pass = 'testpass';

$this->client = static::createClient(array(), array(
    'PHP_AUTH_USER' => $user,
    'PHP_AUTH_PW' => $pass,
    'HTTPS' => true, // Default to HTTPS
));

// Also set a token so the username can be retrieved later
$firewallContext = 'main';
$token = new UsernamePasswordToken($user, $pass, $firewallContext, array('ROLE_ADMIN'));
$ts = $this->client->getContainer()->get('security.token_storage');
$ts->setToken($token);
这在测试用例的设置实现中

编辑:进一步测试后,还有一件事需要注意。UsernamePasswordToken在加载装置时使用,PHP_AUTH_用户在运行测试时使用。这意味着您可以作为一个用户填充初始数据,然后让其他用户运行测试。这很方便,可以确保将任何“上次更新人”字段更改为正确的用户名


如果您像我一样使用条令事件订阅服务器,那么prePersist钩子将看到UsernamePasswordToken用户,而preUpdate钩子将看到PHP_AUTH_用户用户。

您的测试看起来如何?@Malvineous Authentication在测试用例中工作,能够让用户进入测试,但无法让用户进入订阅服务器任何建议