Модульное тестирование FOSUserBundle


Я работаю над созданием сайта с fosUserBundle. Мне нужно написать несколько модульных тестов, но я не могу заставить аутентификацию работать правильно для использования с ними. Я попробовал несколько методов, но безуспешно.

Approach1-цепочка поставщиков в настройках безопасности, чтобы сделать стандартный вход, на который я могу положиться. Когда я делаю это, единственная аутентификация, которая работает, - это поставщик in_memory, то есть я могу войти в систему с пользователем admin, но не с любыми пользователями, созданными fosUserBundle

Безопасность.yml

security:
    encoders:
        "FOSUserBundleModelUserInterface": plaintext
        "SymfonyComponentSecurityCoreUserUser": plaintext

    providers:
        chain_provider:
            providers: [in_memory, fos_userbundle]
        in_memory:
            users:
                admin: { password: admin, roles: [ 'ROLE_ADMIN' ] }
        fos_userbundle:
            id: fos_user.user_manager


    firewalls:
        main:
            pattern: ^/
            form_login:
                provider: fos_userbundle
                login_path:  /
                csrf_provider: form.csrf_provider
                default_target_path: /media
            logout:       true
            anonymous:    true
            http_basic:
                provider: in_memory

Метод 2-я создал пользователя в своей настройке модульного теста. Но с помощью этого метода я никогда не смогу войти в систему с пользователем, которого я только что создал, мне не требуется подтверждение пользователя.

 public function setUp() {

        $kernel = static::createKernel();
        $this->repo = $kernel->boot();
        $this->repo = $kernel->getContainer();

        $userManager = $this->repo->get('fos_user.user_manager');

        $email = "testing".(string) self::newRandomNumber()."@test.com";
        $un = "test".(string) self::newRandomNumber();
        $fn = "testin";
        $ln = "laster";
        $pwd = "passworD1";

        $user = $userManager->createUser();

        $user->setEmail($email);
        $user->setUsername($un);
        $user->setFirstName($fn);
        $user->setLastName($ln);
        $user->setPlainPassword($pwd);
        $user->setBimStaff(True);

        // Persist the user to the database         
        $userManager->updateUser($user);

        $this->user = $user;

        $this->client = static::createClient();
        $crawler = $this->client->request('GET', '/');

        $form = $crawler->selectButton('Login')->form();

        // set some values
        $un = 'Lucas'.self::newRandomNumber();
        $form['_username'] = $un;
        $form['_password'] = $pwd;

        // submit the form

        $crawler = $this->client->submit($form);
        print_r($this->client->getResponse());

        $this->client->followRedirects();

    }

Я пробовал как войти в форму, так и обычную аутентификацию http, но ни то, ни другое не работает.

Любое одно имеет какие-либо советы?

Спасибо, Кори

2 4

2 ответа:

Хм, похоже, что если вы цепочка поставщиков в безопасности вы не можете использовать только один из поставщиков, по крайней мере, это решило проблему для меня.

// security.yml 
providers:
    chain_provider:
        providers: [in_memory, fos_userbundle]
    in_memory:
        users:
            admin: { password: admin, roles: [ 'ROLE_ADMIN' ] }
    fos_userbundle:
        id: fos_user.user_manager


firewalls:
    main:
        pattern: ^/
        form_login:
            provider: chain_provider
            login_path:  /
            csrf_provider: form.csrf_provider
            default_target_path: /media
        logout:       true
        anonymous:    true
        http_basic:
            provider: chain_provider
По какой-то причине, как только я поменял обоих провайдеров на chain_provider, он начал сотрудничать.

Мой модульный тест теперь выглядит так

public function setUp() {

    $kernel = static::createKernel();
    $this->repo = $kernel->boot();
    $this->repo = $kernel->getContainer();


    $this->client = static::createClient(array(), array(
        'PHP_AUTH_USER' => 'admin',
        'PHP_AUTH_PW'   => 'admin',
    ));
    $this->client->followRedirects();

}

При копировании этого я бы предложил использовать более надежные пароли для ваших пользователей:)

У меня была та же проблема, но я хотел, чтобы Вариант 2 работал. Ваш пример был почти там и помог мне. Я думаю, что причина, по которой он не работал для вас, заключается в том, что пользователь не был включен. Конструктор пользователей в FOSUserBundle по умолчанию создает отключенных пользователей, поэтому необходимо вызвать $user->setEnable(true)

Вот мой рабочий пример

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

class MyControllerTest extends WebTestCase
{
    private $client = null;

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

    private function logIn()
    {
        $session = $this->client->getContainer()->get('session');

        $userManager = $this->client->getContainer()->get('fos_user.user_manager');

        $user=$userManager->findUserByUsername('tester');
        if (!$user) {
            $user = $userManager->createUser();

            $user->setEmail('test@example.com');
            $user->setUsername('tester');
            $user->setPlainPassword('foo');
            $user->setEnabled(true);
            $user->addRole('ROLE_SUPER_ADMIN');

            $userManager->updateUser($user);
        }

        $firewall = 'main_firewall';
        $token = new UsernamePasswordToken($user, null, $firewall, array('ROLE_SUPER_ADMIN'));

        $session->set('_security_'.$firewall, serialize($token));
        $session->save();

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

    public function testCompleteScenario()
    {
        $this->logIn();

        $crawler = $this->client->request('GET', '/foo/');
        $this->assertEquals(200, $this->client->getResponse()->getStatusCode(),
            "Unexpected HTTP status code for GET /foo/".$this->client->getResponse()->getContent());

    }

}