Commit 1588e2b5 authored by alexpott's avatar alexpott
Browse files

Issue #2880911 by Mile23, dawehner: Remove unused KernelTestBase::getCompiledContainerBuilder()

parent daea0bf7
......@@ -70,8 +70,10 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa
/**
* {@inheritdoc}
*
* Kernel tests are run in separate processes to prevent collisions between
* code that may be loaded by tests.
* Kernel tests are run in separate processes because they allow autoloading
* of code from extensions. Running the test in a separate process isolates
* this behavior from other tests. Subclasses should not override this
* property.
*/
protected $runTestInSeparateProcess = TRUE;
......@@ -131,11 +133,6 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa
*/
protected $container;
/**
* @var \Drupal\Core\DependencyInjection\ContainerBuilder
*/
private static $initialContainerBuilder;
/**
* Modules to enable.
*
......@@ -344,23 +341,13 @@ private function bootKernel() {
// PHPUnit's @test annotations are intentionally ignored/not supported.
return strpos($method->getName(), 'test') === 0;
}));
if ($test_method_count > 1 && !$this->isTestInIsolation()) {
// Clone a precompiled, empty ContainerBuilder instance for each test.
$container = $this->getCompiledContainerBuilder($modules);
}
// Bootstrap the kernel. Do not use createFromRequest() to retain Settings.
$kernel = new DrupalKernel('testing', $this->classLoader, FALSE);
$kernel->setSitePath($this->siteDirectory);
// Boot the precompiled container. The kernel will enhance it with synthetic
// services.
if (isset($container)) {
$kernel->setContainer($container);
unset($container);
}
// Boot a new one-time container from scratch. Ensure to set the module list
// upfront to avoid a subsequent rebuild.
elseif ($modules && $extensions = $this->getExtensionsForModules($modules)) {
if ($modules && $extensions = $this->getExtensionsForModules($modules)) {
$kernel->updateModules($extensions, $extensions);
}
// DrupalKernel::boot() is not sufficient as it does not invoke preHandle(),
......@@ -470,68 +457,6 @@ protected function getDatabaseConnectionInfo() {
return $connection_info;
}
/**
* 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;
}
/**
* Initializes the FileCache component.
*
......@@ -750,15 +675,6 @@ public function tearDownCloseDatabaseConnection() {
}
}
/**
* {@inheritdoc}
*/
public static function tearDownAfterClass() {
// Free up memory: Precompiled container.
self::$initialContainerBuilder = NULL;
parent::tearDownAfterClass();
}
/**
* Installs default configuration for a given list of modules.
*
......@@ -1073,13 +989,20 @@ protected function prepareTemplate(\Text_Template $template) {
}
/**
* Returns whether the current test runs in isolation.
* Returns whether the current test method is running in a separate process.
*
* Note that KernelTestBase will run in a separate process by default.
*
* @return bool
*
* @see \Drupal\KernelTests\KernelTestBase::$runTestInSeparateProcess
* @see https://github.com/sebastianbergmann/phpunit/pull/1350
*
* @deprecated in Drupal 8.4.x, for removal before the Drupal 9.0.0 release.
* KernelTestBase tests are always run in isolated processes.
*/
protected function isTestInIsolation() {
@trigger_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated in Drupal 8.4.x, for removal before the Drupal 9.0.0 release. KernelTestBase tests are always run in isolated processes.', E_USER_DEPRECATED);
return function_exists('__phpunit_run_isolated_test');
}
......
......@@ -10,6 +10,8 @@
/**
* @coversDefaultClass \Drupal\KernelTests\KernelTestBase
* @group PHPUnit
* @group Test
* @group KernelTests
*/
class KernelTestBaseTest extends KernelTestBase {
......@@ -137,22 +139,21 @@ public function testRegister() {
}
/**
* @covers ::getCompiledContainerBuilder
* Tests whether the fixture allows us to install modules and configuration.
*
* The point of this test is to have integration level testing.
* @see ::testSubsequentContainerIsolation()
*/
public function testCompiledContainer() {
public function testContainerIsolation() {
$this->enableModules(['system', 'user']);
$this->assertNull($this->installConfig('user'));
}
/**
* @covers ::getCompiledContainerBuilder
* @depends testCompiledContainer
* Tests whether the fixture can re-install modules and configuration.
*
* The point of this test is to have integration level testing.
* @depends testContainerIsolation
*/
public function testCompiledContainerIsDestructed() {
public function testSubsequentContainerIsolation() {
$this->enableModules(['system', 'user']);
$this->assertNull($this->installConfig('user'));
}
......
<?php
namespace Drupal\Tests\Core\Test;
use Drupal\Tests\UnitTestCase;
use Drupal\KernelTests\KernelTestBase;
/**
* @group Test
* @group legacy
*
* @coversDefaultClass \Drupal\KernelTests\KernelTestBase
*/
class KernelTestBaseTest extends UnitTestCase {
/**
* @expectedDeprecation Drupal\KernelTests\KernelTestBase::isTestInIsolation() is deprecated in Drupal 8.4.x, for removal before the Drupal 9.0.0 release. KernelTestBase tests are always run in isolated processes.
*
* @covers ::isTestInIsolation
*/
public function testDeprecatedIsTestInIsolation() {
$kernel_test = $this->getMockBuilder(KernelTestBase::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$is_isolated = new \ReflectionMethod($kernel_test, 'isTestInIsolation');
$is_isolated->setAccessible(TRUE);
// Assert that the return value is a bool, because this unit test might or
// might not be running in process isolation.
$this->assertInternalType('bool', $is_isolated->invoke($kernel_test));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment