From 38f06c2a087fde27442544ca2fc630d450c0a236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BCrk?= Date: Sun, 27 Apr 2025 16:46:33 +0200 Subject: [PATCH] [TASK] Reset `GeneralUtility::$container` in `UnitTestCase::tearDown()` It could be possible that unit tests sets dependency injection container calling `GeneralUtility::setContainer()` to provide service instances or mocked service instances specific bound to that test, keeping a dirty state for following unit tests. Executing unit tests in other orders, only as a subset or for example randomized can reveal these pullation and eventualy wrong expectation for other tests. [1] This change adds a automatic cleanup to the tearDown for unit tests ensuring a clean state, because there isn't a easy way to reset that within tests without using native php reflection API. So do it in a general place. It may be possible to let the specific test setting such a container intance to fail with the recommendation to refactor the test into a functional test, but is left out for now. [1] https://review.typo3.org/c/Packages/TYPO3.CMS/+/88839 Releases: main, 8, 7 --- Classes/Core/Unit/UnitTestCase.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Classes/Core/Unit/UnitTestCase.php b/Classes/Core/Unit/UnitTestCase.php index dcbaf24d..8543a4bd 100644 --- a/Classes/Core/Unit/UnitTestCase.php +++ b/Classes/Core/Unit/UnitTestCase.php @@ -136,6 +136,18 @@ protected function tearDown(): void } } + // Unit tests may set GeneralUtility::setContainer() with a container instance containing mocked services, + // returning test specific results. Following tests may not expect that specific outcome and thus fail when + // executed in another order (for example using randomized unit tests). Not having a suitable API to reset + // container instance to null we are using reflection API to reset that property in each teardown to ensure + // clean state for following tests. + $containerPropertyReflection = new \ReflectionProperty(GeneralUtility::class, 'container'); + if ($containerPropertyReflection->getValue(null) !== null) { + // Reset container instances set with `GeneralUtility::setContainer()`. + $containerPropertyReflection->setValue(null, null); + // @todo Should we fail the test recommending to transform the test to an functional test ? + } + // Delete registered test files and directories foreach ($this->testFilesToDelete as $absoluteFileName) { $absoluteFileName = GeneralUtility::fixWindowsFilePath(PathUtility::getCanonicalPath($absoluteFileName));