2013-02-19 2 views
12

Я бы написал тест для Symfony2 с FOSUserBundle.Symfony2 - Тесты с FOSUserBundle

На данный момент я пробовал некоторые способы, и никто не работает.

Мне нужна функция типа "createAuthClient".

Вот мой основной класс. Я отправляю его, потому что вы могли лучше понять мою проблему.

<?php 
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; 
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; 
use Symfony\Component\BrowserKit\Cookie; 

class WebTestMain extends WebTestCase 
{ 
    protected static $container; 

    static protected function createClient(array $options = array(), array $server = array()) 
    { 
     $client = parent::createClient($options, $server); 

     self::$container = self::$kernel->getContainer(); 

     return $client; 
    } 

    static function createAuthClient(array $options = array(), array $server = array()) 
    { 
     // see lines below with my tries 
    } 
} 

Первая попытка:

if(static::$kernel === null) 
{ 
    static::$kernel = static::createKernel($options); 
    static::$kernel->boot(); 
} 
if(static::$container === null) 
{ 
    self::$container = self::$kernel->getContainer(); 
} 

$parameters = self::$container->getParameter('test'); 
$server = array_merge(array('HTTP_HOST' => $parameters['host'], 'HTTP_USER_AGENT' => $parameters['useragent']), $server); 

$client = self::createClient($options, $server); 

$userProvider = self::$container->get('fos_user.user_manager'); 
$user = $userProvider->findUserBy(array('id' => 1)); 
$client->getCookieJar()->set(new Cookie('MOCKSESSID', true)); 
$session = self::$kernel->getContainer()->get('session'); 
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles()); 
$client->getContainer()->get('security.context')->setToken($token); 
$session->set('_security_main', serialize($token)); 

return $client; 

Тогда я искал и искал ... Мою вторую попытки.

if(static::$kernel === null) 
{ 
    static::$kernel = static::createKernel($options); 
    static::$kernel->boot(); 
} 
if(static::$container === null) 
{ 
    self::$container = self::$kernel->getContainer(); 
} 

$parameters = self::$container->getParameter('test'); 
$server = array_merge(
    array(
     'HTTP_HOST' => $parameters['host'], 
     'HTTP_USER_AGENT' => $parameters['useragent'], 
     'PHP_AUTH_USER' => 'admin', 
     'PHP_AUTH_PW' => 'admin' 
    ), 
    $server 
); 
$client = static::createClient(array(), array()); 
$client->followRedirects(); 
return $client; 

А вот моя последняя попытка, прежде чем я вывешиваю этот вопрос ...

$client = self::createClient($options, $server); 

$parameters = self::$container->getParameter('test'); 
$server = array_merge(
    array(
     'HTTP_HOST' => $parameters['host'], 
     'HTTP_USER_AGENT' => $parameters['useragent'] 
    ), 
    $server 
); 

$client->setServerParameters($server); 

$usermanager = self::$container->get('fos_user.user_manager'); 
$testuser = $usermanager->createUser(); 
$testuser->setUsername('test'); 
$testuser->setEmail('[email protected]'); 
$testuser->setPlainPassword('test'); 
$usermanager->updateUser($testuser); 

return $client; 

Спасибо заранее.

ответ

17

Лучший способ, который я нашел для проверки с аутентифицированным пользователем, - это просто посетить страницу входа в систему и отправить форму с именем пользователя и паролем, который вы загрузили с прибора. Это может показаться медленным и громоздким, но будет проверять, что на самом деле сделает пользователь. Вы даже можете создать свой собственный метод, чтобы сделать его быстрым и легким.

public function doLogin($username, $password) { 
    $crawler = $this->client->request('GET', '/login'); 
    $form = $crawler->selectButton('_submit')->form(array(
     '_username' => $username, 
     '_password' => $password, 
     ));  
    $this->client->submit($form); 

    $this->assertTrue($this->client->getResponse()->isRedirect()); 

    $crawler = $this->client->followRedirect(); 
} 
+0

Великий информации. Благодаря! – PatrickB

+0

Помог мне :) Спасибо +1 – Code

+1

@ Майкл: Не могли бы вы рассказать мне, как проверить, зарегистрирован ли пользователь, потому что если мы дадим неправильный пароль, чем перенаправление, также произойдет. и $ this-> assertTrue ($ this-> client-> getResponse() -> isRedirect()); это похоже на работу как в – Code

15

Создать AbstractControllerTest и создать авторизованный клиент на setUp() следующим образом:

<?php 
// ... 
use Symfony\Component\BrowserKit\Cookie; 

abstract class AbstractControllerTest extends WebTestCase 
{ 
    /** 
    * @var Client 
    */ 
    protected $client = null; 


    public function setUp() 
    { 
     $this->client = $this->createAuthorizedClient(); 
    } 

    /** 
    * @return Client 
    */ 
    protected function createAuthorizedClient() 
    { 
     $client = static::createClient(); 
     $container = $client->getContainer(); 

     $session = $container->get('session'); 
     /** @var $userManager \FOS\UserBundle\Doctrine\UserManager */ 
     $userManager = $container->get('fos_user.user_manager'); 
     /** @var $loginManager \FOS\UserBundle\Security\LoginManager */ 
     $loginManager = $container->get('fos_user.security.login_manager'); 
     $firewallName = $container->getParameter('fos_user.firewall_name'); 

     $user = $userManager->findUserBy(array('username' => 'REPLACE_WITH_YOUR_TEST_USERNAME')); 
     $loginManager->loginUser($firewallName, $user); 

     // save the login token into the session and put it in a cookie 
     $container->get('session')->set('_security_' . $firewallName, 
      serialize($container->get('security.context')->getToken())); 
     $container->get('session')->save(); 
     $client->getCookieJar()->set(new Cookie($session->getName(), $session->getId())); 

     return $client; 
    } 
} 

ПРИМЕЧАНИЕ: Пожалуйста, замените имя пользователя с тестового пользователя.

Затем, расширяет AbstractControllerTest и использовать глобальную $client делать запросы следующим образом:

class ControllerTest extends AbstractControllerTest 
{ 
    public function testIndexAction() 
    { 
     $crawler = $this->client->request('GET', '/admin/'); 

     $this->assertEquals(
      Response::HTTP_OK, 
      $this->client->getResponse()->getStatusCode() 
     ); 
    } 
} 

Этот метод проверен и работает отлично

+0

@ k0pernikus Я не использую какое-либо пространство имен в моем примере, поэтому он неявно использует глобальное пространство имен, которое не требует использования statment. –

+1

Я нахожу, что создание зависимостей явным образом приводит к неявному соглашению много раз. (Тот факт, что я пишу этот комментарий, должен сделать это очевидным.) В моем текущем проекте у меня есть куча классов «Клиент» из разных сторонних пакетов. Я должен был посмотреть и проверить, пока не понял, что 'Symfony \ Component \ BrowserKit \ Client' был правильным. Ваш ответ, предоставляя хороший рабочий пример, был бы намного полезнее, если бы он включал операторы использования. На данный момент все еще требуется ручная работа по определению решения. – k0pernikus

+0

@ k0pernikus да, у вас есть точка :) –

Смежные вопросы