These are chat archives for Behat/Behat

3rd
Dec 2018
Donald Tyler
@Chekote
Dec 03 2018 14:58
Howdy! I'm writing a Behat Extension and I'm struggling with the dependency injection. I'm hoping you guys and gals can help me out.
I've had success setting up DI services and injecting them via the behat.yml file, like so:
        default:
          extensions:
            Chekote\BehatNounStoreExtension
          suites:
            default:
              path: "%paths.base%/features"
              contexts:
                - Chekote\BehatNounStoreExtension\Context\StoreContext:
                  - "@store"
                  - "@assert"
              services:
                store: Chekote\NounStore\Store
                assert: Chekote\NounStore\Assert
But I don't want the extension users to have to manually define these services themselves. So instead, I'm trying to register them in the extension classes process() method. Like so:
class BehatNounStoreExtension implements Extension
{
  const SERVICE_ID_ASSERT = 'noun.assert';
  const SERVICE_ID_ARGUMENT_TRANSFORMER = 'noun.argument_transformer';
  const SERVICE_ID_STORE = 'noun.store';

  /**
   * {@inheritdoc}
   */
  public function process(ContainerBuilder $container)
  {
    $container->register(self::SERVICE_ID_STORE, Store::class);
    $container->register(self::SERVICE_ID_ASSERT, Assert::class)->addArgument(new Reference(self::SERVICE_ID_STORE));

    $container->autowire(StoreContext::class)
        ->addArgument(new Reference(self::SERVICE_ID_STORE))
        ->addArgument(new Reference(self::SERVICE_ID_ASSERT));
  }

The behat.yml version works fine, but I'm not able to reference the services that are registered in the process() method. After updating the yaml file like so:

        default:
          extensions:
            Chekote\BehatNounStoreExtension
          suites:
            default:
              path: "%paths.base%/features"
              contexts:
                - Chekote\BehatNounStoreExtension\Context\StoreContext:
                  - "@noun.store"
                  - "@noun.assert"

I get the following error:

PHP Fatal error: Uncaught TypeError: Argument 1 passed to Chekote\BehatNounStoreExtension\Context\StoreContext::__construct() must be an instance of Chekote\NounStore\Store, string given in src/Chekote/BehatNounStoreExtension/Context/StoreContext.php:27

Can anyone tell me what I'm doing wrong?
Donald Tyler
@Chekote
Dec 03 2018 18:59

With the autorwire call in the extensions process method, I though I should be able to drop the argument injections from the behat.yml like so:

        default:
          extensions:
            Chekote\BehatNounStoreExtension
          suites:
            default:
              path: "%paths.base%/features"
              contexts:
                - Chekote\BehatNounStoreExtension\Context\StoreContext

But then I get the following error:

Can not find a matching value for an argument `$store` of the method `Chekote\BehatNounStoreExtension\Context\StoreContext::__construct()`.