Мне нужно добавить, а затем из контекста получить дополнительные параметры / конфигурации из файла behat.yml.
Behat не позволяет мне добавлять некоторые случайные параметры в файл behat.yml, поэтому я создал новое собственное расширение. Это расширение позволяет мне передавать определенные значения конфигурации
extensions:
App\Behat\DevToolsExtension:
api_url: "https://api.example.com"
Так что теперь behat не жалуется на новую конфигурацию в файле behat.yml.
Теперь я застрял. Как я могу получить эту конфигурацию из моего расширения во время выполнения?
Я устанавливаю существующие параметры в своем расширении в методе публичной функции load (ContainerBuilder $ container, array $ config) следующим образом:
$container->setParameter($configKey . $key, $config[$key]);
Опять же, есть ли способ извлечь этот объект ContainerBuilder или DevToolsExtension в контексте?
Решением было создать сервисный контейнер и передать в него behats 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);
}