Behat 3 - как получить собственное расширение в контексте

Мне нужно добавить, а затем из контекста получить дополнительные параметры / конфигурацию из файла behat.yml.

Behat не позволяет мне добавлять случайные параметры в файл behat.yml, поэтому я создал новое собственное расширение. Это расширение позволяет мне передавать определенные значения конфигурации

extensions:
    App\Behat\DevToolsExtension:
        api_url: "https://api.example.com"

Итак, теперь behat не жалуется на новую конфигурацию в файле behat.yml.

Теперь я застрял. Как я могу получить эту конфигурацию из моего расширения во время выполнения?

Я устанавливаю существующие параметры в своем расширении в методе загрузки общедоступной функции (ContainerBuilder $ container, array $ config) следующим образом:

$container->setParameter($configKey . $key, $config[$key]);

Опять же, есть ли способ получить этот объект ContainerBuilder или объект DevToolsExtension в контексте?

Редактировать

Решением было создать сервисный контейнер и передать в него поведение ContainerBuilder следующим образом:

class AppExtension implements ExtensionInterface
{
    // ...
    public function load(ContainerBuilder $container, array $config)
    {
        $configKey = $this->getConfigKey() . '.';

        foreach ($this->keys as $key) {
            $keyValue = $configKey . $key;
            $container->setParameter($keyValue, $config[$key]);
        }

        $this->getServiceLocator()->setBehatContainer($container);
    }

А затем используйте локатор сервисов для получения параметров конфигурации.

$value = $this->getBehatContainer()->getParameter($key);

person wormhit    schedule 07.10.2014    source источник


Ответы (2)


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

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

Но… В большинстве случаев это было бы излишним. То же самое может быть (и должно быть) достигнуто с помощью либо внешнего файла конфигурации, который вы можете загрузить из своего контекста, либо путем передачи параметров вашему контексту (точно так же, как вы это делаете сейчас с расширением). Последний вариант может работать не очень хорошо, если у вас есть много контекстов, в которых требуется такая конфигурация.

person Ian Bytchek    schedule 07.10.2014

У меня была эта проблема, и я решил ее для проекта: CLIPBOARD

Конечно, работаю на ~ v3.0 Вероятно, работаю на v2.5.

В вашем классе Exntesion после создания расширения вам понадобится инициализатор, который будет инициализировать любой контекст в системе. Для этого вам нужно создать сервис в контейнере с ContextExtension :: INITIALIZER_TAG и зависит от конфигурации. у меня есть

$container->setParameter('dev_tools_extension.parameters', $config); 

А потом

private function loadContextInitializer(ContainerBuilder $container)
{
    $definition = new Definition(
        'App\Behat\DevToolsExtension\Context\Initializer\DevToolsExtensionInitializer', array(
            '%dev_tools_extension.parameters%'
        )
    );
    $definition->addTag(ContextExtension::INITIALIZER_TAG, array('priority' => 0));
    $container->setDefinition('dev_tools_extension.context_initializer', $definition);
}

Инициализатор реализует Behat \ Behat \ Context \ Initializer \ ContextInitializer с вызываемым Context. Затем вы создаете (например, интерфейс) и вызываете функцию в контексте. У меня есть:

    /**
 * Initializes provided context.
 *
 * @param Context $context
 */
public function initializeContext(Context $context)
{
    if (!$context instanceof ClipboardContextInterface) {
        return;
    }
    /** @var ClipboardContextInterface $context */

    $context->setClipboard($this->clipboard);
}
person timiTao    schedule 18.11.2014