2017-12-19 20 views
0

Symfony 3とDoctrineでは、データベースに「最後に更新された」カラムがあります。これは、変更がテーブルに保存されるたびに自動的にログインユーザのユーザ名に設定されます。Symfonyユニットテスト中にユーザ名を取得できない

私は本当のためのシステムを使用するときに働く、これを行うにはEventSubscriberを使用していますが、私はそれがログインユーザがいないと考えてユニットテストを実行するとき。

を私はhow to implement authentication for unit testsの指示に従ってています基本認証を使用するか、トークンを設定するかの2つの方法をアドバイスします。どちらの方法でも、ユーザーが認証されたかのようにテストを実行できますが、ログインしたユーザーのユーザー名を取得できないため、「最後に更新された」列が正しく設定されているかどうかはテストできません。

私は間違っていますか? EventSubscriberのログインしているユーザーのユーザー名を取得する必要がある他の方法はありますか?

これが本当の要求のために働く私のEventSubscriber実装ですが、テストが実行されているnullのトークンを返します:

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" ] 

EDIT:テストコードは次のようになり@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']); 
} 
+0

あなたのテストはどのように見えますか? – dbrumann

答えて

1

私はこの問題を解決したと思います。私は正しい方法でユーザーを検索していますと仮定 - - それはことが判明あなたは、トークンを自分で設定する必要があります。

$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); 

これは、テストケースのsetUp()実装です。

編集:さらにテストする際には、もう1つ注意すべきことがあります。固定具をロードするときはUsernamePasswordTokenが使用され、テストを実行するときはPHP_AUTH_USERが使用されます。つまり、最初のデータを1人のユーザーとして入力し、別のユーザーにテストを実行させることができます。これは、「最後に更新された」フィールドが正しいユーザー名に変更されていることを確認するのに便利です。

私はとしてDoctrineイベントサブスクライバーを使用している場合preUpdateフックがPHP_AUTH_USERユーザーが表示されますが、その後、prePersistフックは、UsernamePasswordTokenユーザーが表示されます。

+1

はい、この認証はうまくいいですね。 – Mcsky

関連する問題