Problem/Motivation
So this was a doozy to track down and debug.
While working on #2710989: Create a resolver API for picking a checkout flow, I discovered configuration entities which implement \Drupal\Core\Entity\EntityWithPluginCollectionInterface
cannot be run in Kernel tests, due to the fact that their __sleep
methods will invoke the Drupal static class to get the container.
In TestCaseMethod.tpl.dist
the code for __phpunit_run_isolated_test
calls serialize on the test results, number of assertsion, the result and output.
print serialize(
array('testResult' => $test->getResult(),'numAssertions' => $test->getNumAssertions(),'result' => $result,'output' => $output
)
);
This was causing an error like the following (which left me scratching my head)
There was 1 error:
1) Drupal\Tests\commerce_checkout\Kernel\ChainCheckoutFlowResolverTest::testCheckoutFlowResolution
PHPUnit_Framework_Exception: PHP Fatal error: Uncaught Drupal\Core\DependencyInjection\ContainerNotInitializedException: \Drupal::$container is not initialized yet. \Drupal::setContainer() must be called with a real container. in /Users/mglaman/Drupal/sites/commerce2x/web/core/lib/Drupal.php:130
Stack trace:
#0 /Users/mglaman/Drupal/sites/commerce2x/web/core/lib/Drupal.php(159): Drupal::getContainer()
#1 /Users/mglaman/Drupal/sites/commerce2x/web/modules/contrib/commerce/modules/checkout/src/Entity/CheckoutFlow.php(131): Drupal::service('plugin.manager....')
#2 /Users/mglaman/Drupal/sites/commerce2x/web/modules/contrib/commerce/modules/checkout/src/Entity/CheckoutFlow.php(117): Drupal\commerce_checkout\Entity\CheckoutFlow->getPluginCollection()
#3 /Users/mglaman/Drupal/sites/commerce2x/web/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php(357): Drupal\commerce_checkout\Entity\CheckoutFlow->getPluginCollections()
#4 /Users/mglaman/Drupal/sites/commerce2x/web/modules/contrib/commerce/modules/checkout/src/Entity/CheckoutFlow.php(139): Drupal\Core\Conf in /Users/mglaman/Drupal/sites/commerce2x/web/core/lib/Drupal.php on line 130
So I threw an exception in the CheckoutFlow
entity's __sleep
method and got (stack trace json-ified in exception message)
There was 1 error:
1) Drupal\Tests\commerce_checkout\Kernel\ChainCheckoutFlowResolverTest::testCheckoutFlowResolution
PHPUnit_Framework_Exception: PHP Fatal error: Uncaught Exception: [{"function":"__sleep","class":"Drupal\\commerce_checkout\\Entity\\CheckoutFlow","object":{},"type":"->","args":[]},{"file":"-","line":68,"function":"serialize","args":[{"testResult":null,"numAssertions":5,"result":{},"output":""}]},{"file":"-","line":1354,"function":"__phpunit_run_isolated_test","args":[]}] in /Users/mglaman/Drupal/sites/commerce2x/web/modules/contrib/commerce/modules/checkout/src/Entity/CheckoutFlow.php:139
Stack trace:
#0 [internal function]: Drupal\commerce_checkout\Entity\CheckoutFlow->__sleep()
#1 -(68): serialize(Array)
#2 -(1354): __phpunit_run_isolated_test()
#3 {main}
thrown in /Users/mglaman/Drupal/sites/commerce2x/web/modules/contrib/commerce/modules/checkout/src/Entity/CheckoutFlow.php on line 139
The \Drupal\Core\Config\Entity\ConfigEntityBase::__sleep
method invokes ::getPluginCollections
which ends up touching \Drupal::service
in some way or form. In core we have: FilterFormat, ImageStyle, RestResourceConfig, SearchPage, and Action. All of these will throw the same errors if run in a kernel test.
Proposed resolution
No idea.
Remaining tasks
- Investigate how to prevent ConfigEntity objects from being serialize at the end of a test method life cycle
- See how to mitigate needing
\Drupal::service
in these entity classes?