nuvoleweb / drupal-behat

Nuvole's Behat Drupal Extension.
GNU General Public License v2.0
33 stars 24 forks source link

Support obtaining custom services from static methods #58

Open rthideaway opened 3 years ago

rthideaway commented 3 years ago

I love the feature to define custom services in behat tests and then use them across Context(s). However I experienced the problem when they are not accessible from static methods. This make it unable to access any custom service from behat hooks like

  /**
   * Creates the test entities before the test suite starts.
   *
   * @BeforeFeature @sometest
   */
  public static function createTestEntities(): void {
     // Custom behat service is obviously not presented in drupal's container
     // and there is no way to access the plugin's one.
     $service_not_recognized = \Drupal::service('my_test.behat.service');
  }

Would it be possible to implement the way to obtain plugin's container to get the custom services from static methods as well? Or by some other way? That would be really really amazing. I searched for a way if I be able to get the container from static methods, but had no luck so far.

bircher commented 3 years ago

I think it would probably be possible. But I am not sure that it would not create more problems than it is worth. If you call this new static get method then it would throw an exception when the container was not set before. The same is true also with \Drupal::service() of course. So it may work, but it may not, using the container via non static methods means your code needs to live as a method on an initialized object.

That said if you want something like this then you can create a new context with the following code:


use Drupal\Core\DependencyInjection\ContainerNotInitializedException;
use NuvoleWeb\Drupal\DrupalExtension\Context\RawDrupalContext;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class StaticServiceContext extends RawDrupalContext
{

  protected static $staticContainer = NULL;

  public function setContainer(ContainerBuilder $container)
  {
    parent::setContainer($container);
    static::$staticContainer = $container;
  }

  public static function getStaticContainer() {
    if (static::$staticContainer === NULL) {
      throw new ContainerNotInitializedException('\StaticServiceContext::$container is not initialized yet.');
    }
    return static::$staticContainer;
  }

  public static function service($id) {
    return static::getStaticContainer()->get($id);
  }

}