Behat аутентифицировать пользователя Symfony2 - PullRequest
12 голосов
/ 13 ноября 2011

Я использую Behat в Symfony2 / Doctrine2. Теперь у меня есть сценарий, который сводится к тому, что «если я вошел в систему и захожу в / login, я должен перейти в / вместо»:

@login
Scenario: Go to the login page while being logged in
  Given I am logged in
  When I go to "/login"
  Then I should be on "/"

Для @login я создал следующее:

/**
 * @BeforeScenario @login
 */
public function loginUser()
{
    $doctrine = $this->getContainer()->get('doctrine');
    $userRepository = $doctrine->getRepository('MyTestBundle:User');
    $user = $userRepository->find(1); // 1 = id

    $token = new UsernamePasswordToken($user, NULL, 'main', $user->getRoles());
    $this->getContainer()->get('security.context')->setToken($token);
}

В коде "когда я иду / вход в систему" (вызывается контроллер) токен, кажется, пропал (не то, что я намеревался):

/**
 * @Route("/login", name="login")
 */
public function loginAction()
{
    $token = $this->get('security.context')->getToken();
    $fd = fopen('/tmp/debug.log', 'a');
    fwrite($fd, $token);

    // prints 'AnonymousToken(user="anon.", authenticated=true, roles="")'
    ...

Но в FeatureContext он, кажется, держится (как я надеялся, это сработает). В поле «Дано, я вошел в систему»:

/**
 * @Given /^I am logged in$/
 */
public function iAmLoggedIn()
{        
    $token = $this->getContainer()->get('security.context')->getToken();
    $fd = fopen('/tmp/debug.log', 'a');
    fwrite($fd, $token);

    // prints 'UsernamePasswordToken(user="admin", authenticated=true, roles="ROLE_ADMIN")'
    ...

Я бегу вот так:

app/console -e=test behat

Я также сделал это в контроллере, чтобы убедиться, что это тест:

fwrite($fd, $this->get('kernel')->getEnvironment());
// prints 'test'

Любая подсказка, как аутентифицировать пользователя? Мне нужно будет протестировать множество страниц администратора, поэтому было бы неплохо, если бы я мог подключить вход в @BeforeSuite, @BeforeFeature (или @BeforeScenario ...), чтобы меня не блокировали.

(Также приветствуются предложения по отключению механизма аутентификации для тестирования или способу заглушить / издеваться над пользователем.)

Ответы [ 4 ]

19 голосов
/ 13 ноября 2011

О боже.Он не работает, потому что DIC внутри вашего FeatureContext не используется совместно с вашим приложением - ваше приложение имеет отдельное ядро ​​и DIC.Вы можете получить это через Норку.Или вы можете просто сделать это правильно: -)

Правильный путь означает, что каждая часть поведения, наблюдаемая конечным пользователем, должна быть описана внутри * .feature, а не внутри FeatureContext.Это означает, что если вы хотите войти в систему пользователя, вы должны просто описать его с помощью шагов (например: «я нахожусь / логин», «и я ввожу имя пользователя ...», «я заполняю пароль» и Stuf),Если вы хотите сделать это несколько раз - вы должны создать метастеп.

Метастепы - это просто шаги, которые описывают множество других шагов, например - «я вошел как everzet».Вы можете прочитать о них здесь: http://docs.behat.org/guides/2.definitions.html#step-execution-chaining

1 голос
/ 08 декабря 2014

http://robinvdvleuten.nl/blog/handle-authenticated-users-in-behat-mink/ - это простая, чистая статья о том, как создать сеанс входа в систему и установить cookie сеанса Mink таким образом, чтобы сеанс Mink входил в систему. Это гораздо лучше, чем каждый раз использовать форму входа в систему для входа в систему. пользователь.

1 голос
/ 03 октября 2013

Вот решение для входа через OAuth, которое я использовал.После нескольких раз поиска ответа и посадки на эту страницу я подумал, что было бы здорово поделиться решением.Надеюсь, это кому-нибудь поможет.

Фон : приложение Symfony2, использующее HWIOAuthBundle, подключенное к какому-либо провайдеру OAuth2.

Проблема : как реализоватьGiven I'm logged in когда контекст Behat не используется совместно с контекстом Symfony?

Решение :

HWIOAuthBundle использует сервис @buzz для всех вызовов API для поставщиков OAuth.Поэтому все, что вам нужно сделать, это заменить клиент Buzz своей реализацией, которая не вызывает внешние службы, но сразу же возвращает результат.Это моя реализация:

<?php

namespace Acme\ExampleBundle\Mocks;

use Buzz\Client\ClientInterface;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;

class HttpClientMock implements ClientInterface
{
    public function setVerifyPeer()
    {
        return $this;
    }

    public function setTimeout()
    {
        return $this;
    }

    public function setMaxRedirects()
    {
        return $this;
    }

    public function setIgnoreErrors()
    {
        return $this;
    }

    public function send(RequestInterface $request, MessageInterface $response)
    {
        if(preg_match('/\/oauth2\/token/', $request->getResource()))
        {
            $response->setContent(json_encode([
                'access_token' => 'valid',
                'token_type' => 'bearer',
                'expires_in' => 3600
            ]));
        }
        elseif(preg_match('/\/oauth2\/me/', $request->getResource()))
        {
            $response->setContent(json_encode([
                'id' => 1,
                'username' => 'doctor',
                'realname' => 'Doctor Who'
            ]));
        }
        else throw new \Exception('This Mock object doesn\'t support this resource');
    }
}

Следующий шаг - захватить класс, используемый HWIOAuthBundle / Buzz, и заменить его реализацией, описанной выше.Нам нужно сделать это только для тестовой среды.

# app/config/config_test.yml
imports:
    - { resource: config_dev.yml }

parameters:
    buzz.client.class: Acme\ExampleBundle\Mocks\HttpClientMock

И, наконец, вам нужно установить для require_previous_session значение false для тестовой среды - поэтому я предлагаю передать его в качестве параметра.

# app/config/security.yml
security:
    firewalls:
        secured_area:
            oauth:
                require_previous_session: false

Теперь вы можете реализовать свой шаг следующим образом.

Спецификация:

Feature: Access restricted resource

  Scenario: Access restricted resource
    Given I'm logged in
    When I go to "/secured-area"
    Then I should be on "/secured-area"
    And the response status code should be 200

Реализация:

<?php
/**
 * @Given /^I\'m logged in$/
 */
public function iMLoggedIn()
{
    $this->getSession()->visit($this->locatePath('/login/check-yourOauthProvider?code=validCode'));
}

Код, который вы передаете, не имеет значения,все, что вы передадите, будет в порядке, так как оно не проверяется.Вы можете настроить это поведение в методе HttpClientMock::send.

0 голосов
/ 21 октября 2013

Здесь можно вызывать слой «внутри» слоя пользовательского интерфейса (в Symfony: поговорите с моделями).И для всех пользователей Symfony, вот, рекомендует использовать данный шаг с аргументами таблиц для установки записей вместо фикстур.Таким образом, вы можете прочитать сценарий в одном месте и понять его, не переходя между файлами:

Учитывая, что есть пользователи:
|имя пользователя |пароль |электронная почта |
|эверзет |123456 |everzet@knplabs.com |
|Фабпот |22 @ 222 |fabpot@symfony.com |

...