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

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

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

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

Поэтому сейчас не жалуйтесь на новую конфигурацию в файле behat.yml.

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

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

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

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

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

Решение заключалось в создании сервисного контейнера и вступлении к нему в 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); 

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

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

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

У меня была эта проблема, и я решил это для проекта: 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 с вызываемым контекстом. Затем вы создаете (например, интерфейс) и вызываете функцию в контексте. У меня есть:

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