Exemplo n.º 1
0
 /**
  * Prepares a precompiled ContainerBuilder for all tests of this class.
  *
  * Avoids repetitive calls to ContainerBuilder::compile(), which is very slow.
  *
  * Based on the (always identical) list of $modules to enable, an initial
  * container is compiled, all instantiated services are reset/removed, and
  * this precompiled container is stored in a static class property. (Static,
  * because PHPUnit instantiates a new class instance for each test *method*.)
  *
  * This method is not invoked if there is only a single test method. It is
  * also not invoked for tests running in process isolation (since each test
  * method runs in a separate process).
  *
  * The ContainerBuilder is not dumped into the filesystem (which would yield
  * an actually compiled Container class), because
  *
  * 1. PHP code cannot be unloaded, so e.g. 900 tests would load 900 different,
  *    full Container classes into memory, quickly exceeding any sensible
  *    memory consumption (GigaBytes).
  * 2. Dumping a Container class requires to actually write to the system's
  *    temporary directory. This is not really easy with vfs, because vfs
  *    doesn't support yet "include 'vfs://container.php'.". Maybe we could fix
  *    that upstream.
  * 3. PhpDumper is very slow on its own.
  *
  * @param string[] $modules
  *   The list of modules to enable.
  *
  * @return \Drupal\Core\DependencyInjection\ContainerBuilder
  *   A clone of the precompiled, empty service container.
  */
 private function getCompiledContainerBuilder(array $modules)
 {
     if (!isset(self::$initialContainerBuilder)) {
         $kernel = new DrupalKernel('testing', $this->classLoader, FALSE);
         $kernel->setSitePath($this->siteDirectory);
         if ($modules && ($extensions = $this->getExtensionsForModules($modules))) {
             $kernel->updateModules($extensions, $extensions);
         }
         $kernel->boot();
         self::$initialContainerBuilder = $kernel->getContainer();
         // Remove all instantiated services, so the container is safe for cloning.
         // Technically, ContainerBuilder::set($id, NULL) removes each definition,
         // but the container is compiled/frozen already.
         foreach (self::$initialContainerBuilder->getServiceIds() as $id) {
             self::$initialContainerBuilder->set($id, NULL);
         }
         // Destruct and trigger garbage collection.
         \Drupal::unsetContainer();
         $kernel->shutdown();
         $kernel = NULL;
         // @see register()
         $this->container = NULL;
     }
     $container = clone self::$initialContainerBuilder;
     return $container;
 }