2017-12-19 34 views
0

Symfony 3에서 Doctrine과 함께 데이터베이스에 "마지막으로 업데이트 한"컬럼이 있습니다. 변경 사항이 테이블에 저장 될 때마다 로그인 된 사용자의 사용자 이름으로 자동 설정됩니다. .Symfony 유닛 테스트 중에 사용자 이름을 얻을 수 없습니다.

내가 진짜 시스템을 사용할 때 작동하는이 작업을 수행하기 위해 EventSubscriber를 사용하여,하지만 난 그게 생각하는 단위 테스트를 실행할 때 로그인 한 사용자가없는입니다.

을 내가 how to implement authentication for unit tests의 지침에 따라입니다 기본 인증을 사용하거나 토큰을 설정하는 두 가지 방법을 조언합니다. 이 두 방법 모두 사용자가 인증 된 것처럼 테스트를 실행할 수 있지만 둘 다 로그인 한 사용자의 사용자 이름을 검색 할 수 없기 때문에 "마지막 업데이트 기준"열이 올바르게 설정되어 있는지 테스트 할 수 없습니다.

내가 뭘 잘못하고 있니? 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']); 
} 
+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() 구현에 있습니다 토큰을 직접 설정해야합니다 - 나는 올바른 방법으로 사용자를 검색하고 가정 - 그것은 것으로 나타났다.

편집 : 추가 테스트시 알아 두어야 할 사항이 하나 더 있습니다. 조명기를 로딩 할 때 UsernamePasswordToken을 사용하고 테스트를 실행할 때 PHP_AUTH_USER을 사용합니다. 즉, 초기 데이터를 한 사용자로 채운 다음 다른 사용자가 테스트를 실행할 수 있습니다. 이것은 '마지막 업데이트 기준'필드가 올바른 사용자 이름으로 변경되도록하기 위해 편리합니다. 나는 당신이 교리 이벤트 가입자를 사용하는 경우 preUpdate 후크가 PHP_AUTH_USER 사용자를 볼 때

는 다음 prePersist 후크는 UsernamePasswordToken 사용자를 볼 수 있습니다.

+1

예이 인증은 훌륭하게 잘되어 있습니다. – Mcsky