Подтвердить что ты не робот

Быть аутентифицированным пользователем Symfony2

Я использую 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);
}

В коде "When я go to/login" (вызов контроллера вызывается) маркер кажется пропавшим (не то, что я намеревался):

/**
 * @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...), чтобы я не блокировался.

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Вот решение для входа в систему с использованием 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.

Ответ 3

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

Ответ 4

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

Учитывая, что есть пользователи:
| имя пользователя | пароль | электронная почта | | everzet | 123456 | [email protected] | | fabpot | 22 @222 | [email protected] |