function KernelTestBase::bootKernel

Same name and namespace in other branches
  1. 11.x core/tests/Drupal/KernelTests/KernelTestBase.php \Drupal\KernelTests\KernelTestBase::bootKernel()
  2. 10 core/tests/Drupal/KernelTests/KernelTestBase.php \Drupal\KernelTests\KernelTestBase::bootKernel()
  3. 9 core/tests/Drupal/KernelTests/KernelTestBase.php \Drupal\KernelTests\KernelTestBase::bootKernel()
  4. 8.9.x core/tests/Drupal/KernelTests/KernelTestBase.php \Drupal\KernelTests\KernelTestBase::bootKernel()

Bootstraps a kernel for a test.

2 calls to KernelTestBase::bootKernel()
KernelTestBase::setUp in core/tests/Drupal/KernelTests/KernelTestBase.php
SuperUserPermissionsTest::testPermissionChange in core/tests/Drupal/KernelTests/Core/Session/SuperUserPermissionsTest.php
Tests the super user access policy grants all permissions.
1 method overrides KernelTestBase::bootKernel()
DrupalKernelTest::bootKernel in core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php
Bootstraps a kernel for a test.

File

core/tests/Drupal/KernelTests/KernelTestBase.php, line 435

Class

KernelTestBase
Base class for functional integration tests.

Namespace

Drupal\KernelTests

Code

protected function bootKernel() : void {
  $this->setSetting('container_yamls', []);
  // Allow for test-specific overrides.
  $settings_services_file = $this->root . '/sites/default/testing.services.yml';
  if (file_exists($settings_services_file)) {
    // Copy the testing-specific service overrides in place.
    $testing_services_file = $this->siteDirectory . '/services.yml';
    copy($settings_services_file, $testing_services_file);
    $this->setSetting('container_yamls', [
      $testing_services_file,
    ]);
  }
  // Allow for global test environment overrides.
  if (file_exists($test_env = $this->root . '/sites/default/testing.services.yml')) {
    $GLOBALS['conf']['container_yamls']['testing'] = $test_env;
  }
  // Add this test class as a service provider.
  $GLOBALS['conf']['container_service_providers']['test'] = $this;
  $modules = self::getModulesToEnable(static::class);
  // When a module is providing the database driver, then enable that module.
  $connection_info = Database::getConnectionInfo();
  $namespace = $connection_info['default']['namespace'] ?? '';
  $autoload = $connection_info['default']['autoload'] ?? '';
  if (str_contains($autoload, 'src/Driver/Database/')) {
    [$first, $second] = explode('\\', $namespace, 3);
    if ($first === 'Drupal' && strtolower($second) === $second) {
      // Add the module that provides the database driver to the list of
      // modules as the first to be enabled.
      array_unshift($modules, $second);
    }
  }
  // Bootstrap the kernel. Do not use createFromRequest() to retain Settings.
  $kernel = new KernelTestDrupalKernel('testing', $this->classLoader, static::sharesEnvironment());
  $kernel->setSitePath($this->siteDirectory);
  // Boot a new one-time container from scratch. Set the module list upfront
  // to avoid a subsequent rebuild or setting the kernel into the
  // pre-installer mode.
  $extensions = $modules ? $this->getExtensionsForModules($modules) : [];
  $kernel->updateModules($extensions, $extensions);
  if (static::sharesEnvironment()) {
    $kernel->setContainerNeedsRebuild(FALSE);
    $kernel->setOverrideUseCache(TRUE);
  }
  // DrupalKernel::boot() is not sufficient as it does not invoke preHandle(),
  // which is required to initialize legacy global variables.
  $request = Request::create('/');
  $kernel->boot();
  $request->attributes
    ->set(RouteObjectInterface::ROUTE_OBJECT, new Route('<none>'));
  $request->attributes
    ->set(RouteObjectInterface::ROUTE_NAME, '<none>');
  $this->container = $kernel->getContainer();
  $this->keyValue = $this->container
    ->get('keyvalue');
  $kernel->preHandle($request);
  // Run database tasks and check for errors.
  $installer_class = $namespace . "\\Install\\Tasks";
  $errors = (new $installer_class())->runTasks();
  if (!empty($errors)) {
    $this->fail('Failed to run installer database tasks: ' . implode(', ', $errors));
  }
  // Setup the destination to the be frontpage by default.
  \Drupal::destination()->set('/');
  // Write the core.extension configuration.
  // Required for ConfigInstaller::installDefaultConfig() to work.
  //
  // The module list is rebuilt from scratch for every test method, so that a
  // test method enabling a module does not leak it into the ones that follow
  // it. The theme list is kept instead, because installing a theme writes its
  // default configuration, which a test class sharing its environment does
  // once, in ::setUpEnvironment().
  $config_storage = $this->container
    ->get('config.storage');
  $themes = [];
  if (static::sharesEnvironment() && $extension = $config_storage->read('core.extension')) {
    $themes = $extension['theme'] ?? [];
  }
  $config_storage->write('core.extension', [
    'module' => array_fill_keys($modules, 0),
    'theme' => $themes,
  ]);
  $settings = Settings::getAll();
  $settings['php_storage']['default'] = [
    'class' => '\\Drupal\\Component\\PhpStorage\\FileStorage',
  ];
  new Settings($settings);
  // Manually configure the test mail collector implementation to prevent
  // tests from sending out emails and collect them in state instead.
  // While this should be enforced via settings.php prior to installation,
  // some tests expect to be able to test mail system implementations.
  $GLOBALS['config']['system.mail']['interface']['default'] = 'test_mail_collector';
  $GLOBALS['config']['system.mail']['mailer_dsn'] = [
    'scheme' => 'null',
    'host' => 'null',
    'user' => NULL,
    'password' => NULL,
    'port' => NULL,
    'options' => [],
  ];
  // Manually configure the default file scheme so that modules that use file
  // functions don't have to install system and its configuration.
  // @see file_default_scheme()
  $GLOBALS['config']['system.file']['default_scheme'] = 'public';
  if (!static::sharesEnvironment()) {
    return;
  }
  $record = $this->loadSharedDatabaseState();
  // For each method in the test, reset the kernel container cache suffix to
  // 0. This ensures that the initial container state is the same for each
  // method, while container rebuilds during tests will force a new cache key.
  $kernel->resetCacheSuffix();
  // Reset the container so it is always reloaded from the cache and any
  // stateful services lose their state.
  // @todo revisit as part of https://www.drupal.org/node/2218651
  $kernel->resetContainer();
  if ($record === NULL) {
    try {
      $this->setUpEnvironment();
    } catch (\Throwable $e) {
      // The initial state is half built. Record that, so the test methods
      // that follow report this failure properly.
      $this->invalidateDatabaseState(sprintf('%s::setUpEnvironment() failed: %s', static::class, $e->getMessage()));
      throw $e;
    }
    $this->environmentTables = $this->getSharedStateTables();
    $this->createStateTable($this->environmentTables);
  }
  elseif ($record['status'] !== 'ready') {
    throw new \RuntimeException(sprintf("The shared database state of %s was invalidated by an earlier test method and is not rebuilt, so this test method cannot run. The reason was:\n%s", static::class, $record['message']));
  }
  elseif ($record['tables'] !== NULL) {
    $this->environmentTables = Json::decode($record['tables']);
  }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.