diff --git a/typo3/sysext/core/Tests/Functional/Utility/File/ExtendedFileUtilityTest.php b/typo3/sysext/core/Tests/Functional/Utility/File/ExtendedFileUtilityTest.php
index dba6efe0d743cb1421f66f0065faebd7733d1a20..93a09966711be2e1b2dd9e8c417076babfd260ec 100644
--- a/typo3/sysext/core/Tests/Functional/Utility/File/ExtendedFileUtilityTest.php
+++ b/typo3/sysext/core/Tests/Functional/Utility/File/ExtendedFileUtilityTest.php
@@ -27,14 +27,14 @@ use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
 final class ExtendedFileUtilityTest extends FunctionalTestCase
 {
     protected array $pathsToProvideInTestInstance = [
-        'typo3/sysext/core/Tests/Functional/Utility/Fixtures/Folders/' => 'fileadmin/',
+        'typo3/sysext/core/Tests/Functional/Utility/File/Fixtures/Folders/' => 'fileadmin/',
     ];
 
     public function setUp(): void
     {
         parent::setUp();
-        $this->importCSVDataSet(__DIR__ . '/../Fixtures/DataSet/sys_refindex.csv');
-        $this->importCSVDataSet(__DIR__ . '/../Fixtures/DataSet/sys_file.csv');
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/DataSet/sys_refindex.csv');
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/DataSet/sys_file.csv');
         $GLOBALS['LANG'] = GeneralUtility::makeInstance(LanguageServiceFactory::class)->create('default');
     }
 
diff --git a/typo3/sysext/core/Tests/Functional/Utility/Fixtures/DataSet/sys_file.csv b/typo3/sysext/core/Tests/Functional/Utility/File/Fixtures/DataSet/sys_file.csv
similarity index 100%
rename from typo3/sysext/core/Tests/Functional/Utility/Fixtures/DataSet/sys_file.csv
rename to typo3/sysext/core/Tests/Functional/Utility/File/Fixtures/DataSet/sys_file.csv
diff --git a/typo3/sysext/core/Tests/Functional/Utility/Fixtures/DataSet/sys_refindex.csv b/typo3/sysext/core/Tests/Functional/Utility/File/Fixtures/DataSet/sys_refindex.csv
similarity index 100%
rename from typo3/sysext/core/Tests/Functional/Utility/Fixtures/DataSet/sys_refindex.csv
rename to typo3/sysext/core/Tests/Functional/Utility/File/Fixtures/DataSet/sys_refindex.csv
diff --git a/typo3/sysext/core/Tests/Functional/Utility/Fixtures/Folders/FolderWithUnusedFile/unused.txt b/typo3/sysext/core/Tests/Functional/Utility/File/Fixtures/Folders/FolderWithUnusedFile/unused.txt
similarity index 100%
rename from typo3/sysext/core/Tests/Functional/Utility/Fixtures/Folders/FolderWithUnusedFile/unused.txt
rename to typo3/sysext/core/Tests/Functional/Utility/File/Fixtures/Folders/FolderWithUnusedFile/unused.txt
diff --git a/typo3/sysext/core/Tests/Functional/Utility/Fixtures/Folders/FolderWithUsedFile/used.txt b/typo3/sysext/core/Tests/Functional/Utility/File/Fixtures/Folders/FolderWithUsedFile/used.txt
similarity index 100%
rename from typo3/sysext/core/Tests/Functional/Utility/Fixtures/Folders/FolderWithUsedFile/used.txt
rename to typo3/sysext/core/Tests/Functional/Utility/File/Fixtures/Folders/FolderWithUsedFile/used.txt
diff --git a/typo3/sysext/core/Tests/Functional/Utility/Fixtures/RootlineScenario.yaml b/typo3/sysext/core/Tests/Functional/Utility/Fixtures/RootlineScenario.yaml
deleted file mode 100644
index 6f4a1a8bdc076e7e36f657bbfdc9b5209428948c..0000000000000000000000000000000000000000
--- a/typo3/sysext/core/Tests/Functional/Utility/Fixtures/RootlineScenario.yaml
+++ /dev/null
@@ -1,58 +0,0 @@
-__variables:
-  - &pageStandard 0
-  - &pageShortcut 4
-  - &pageMount 7
-
-entitySettings:
-  '*':
-    nodeColumnName: 'pid'
-    columnNames: {id: 'uid', language: 'sys_language_uid'}
-    defaultValues: {pid: 0}
-  page:
-    isNode: true
-    tableName: 'pages'
-    parentColumnName: 'pid'
-    languageColumnNames: ['l10n_parent', 'l10n_source']
-    columnNames: {type: 'doktype', root: 'is_siteroot', mount: 'mount_pid', showContentOfMountedPage: 'mount_pid_ol', visitorGroups: 'fe_group'}
-    defaultValues: {hidden: 0, doktype: *pageStandard}
-    valueInstructions:
-      shortcut:
-        first: {shortcut: 0, shortcut_mode: 1}
-  workspace:
-    tableName: 'sys_workspace'
-
-entities:
-  workspace:
-    - self: {id: 1, title: 'My Personal Workspace' }
-    - self: {id: 2, title: 'Another Workspace' }
-  page:
-    - self: {id: 1000, title: 'ACME Global', type: *pageShortcut, shortcut: 'first', root: true, slug: '/'}
-      versionVariants:
-        - version: { workspace: 1, title: 'ACME Global modified in Workspace 1' }
-      children:
-        - self: {id: 1100, title: 'EN: Welcome', slug: '/welcome' }
-          languageVariants:
-            - self: {id: 1101, title: 'FR: Welcome', language: 1, slug: '/bienvenue' }
-            - self: {id: 1102, title: 'FR-CA: Welcome', language: 2, slug: '/bienvenue' }
-        - self: {id: 1200, title: 'EN: Features', slug: '/features'}
-          children:
-            - self: {id: 1210, title: 'EN: Frontend Editing', slug: '/features/frontend-editing'}
-        - self: {id: 1300, title: 'EN: Products', slug: '/products'}
-          versionVariants:
-            - version: { workspace: 2 }
-              actions:
-                - { action: 'delete' }
-          children:
-            - self: {id: 1310, title: 'EN: Toys', slug: '/products/toys'}
-            - self: {id: 1320, title: 'EN: Card Games', slug: '/products/card-games'}
-            - self: {id: 1330, title: 'EN: Board Games', slug: '/products/board-games'}
-              children:
-                - self: {id: 1331, title: 'EN: Monopoly', slug: '/products/monopoly'}
-                - self: {id: 1332, title: 'EN: Catan', slug: '/products/board-games/catan'}
-                - self: {id: 1333, title: 'EN: Risk', slug: '/risk'}
-                  versionVariants:
-                    - version: { workspace: 1 }
-                      actions:
-                        - { action: 'move', type: 'toPage', target: 1320 }
-        - version: {id: 1400, title: 'EN: A new page in workspace', slug: '/a-new-page', workspace: 1 }
-    - self: {id: 9999, title: 'Another root page as dummy to incremental numbers', root: true, slug: '/'}
diff --git a/typo3/sysext/core/Tests/Functional/Utility/Fixtures/RootlineUtilityImport.csv b/typo3/sysext/core/Tests/Functional/Utility/Fixtures/RootlineUtilityImport.csv
new file mode 100644
index 0000000000000000000000000000000000000000..40c388c886f9fd6009d5f4a4a10c99f67e741bb6
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/Utility/Fixtures/RootlineUtilityImport.csv
@@ -0,0 +1,26 @@
+"sys_workspace"
+,"uid","pid","deleted","title"
+,1,0,0,"My Personal Workspace"
+,2,0,0,"Another Workspace"
+"pages"
+,"uid","pid","deleted","sys_language_uid","l10n_parent","t3ver_wsid","t3ver_oid","t3ver_state","media","mount_pid","mount_pid_ol","fe_group","slug","title"
+,1000,0,0,0,0,0,0,0,0,0,0,0,"/","ACME Global"
+,1100,1000,0,0,0,0,0,0,0,0,0,0,"/welcome","EN: Welcome"
+,1101,1000,0,1,1100,0,0,0,0,0,0,0,"/bienvenue","FR: Welcome"
+,1102,1000,0,2,1100,0,0,0,0,0,0,0,"/bienvenue-ca","FR-CA: Welcome"
+,1200,1000,0,0,0,0,0,0,0,0,0,0,"/features","EN: Features"
+,1300,1000,0,0,0,0,0,0,0,0,0,0,"/products","EN: Products"
+,1310,1300,0,0,0,0,0,0,0,0,0,0,"/products/toys","EN: Toys"
+,1320,1300,0,0,0,0,0,0,0,0,0,0,"/products/card-games","EN: Card Games"
+,1330,1300,0,0,0,0,0,0,0,0,0,0,"/products/board-games","EN: Board Games"
+,1331,1330,0,0,0,0,0,0,0,0,0,0,"/products/monopoly","EN: Monopoly"
+,1332,1330,0,0,0,0,0,0,0,0,0,0,"/products/board-games/catan","EN: Catan"
+,1333,1330,0,0,0,0,0,0,0,0,0,0,"/risk","EN: Risk"
+,1400,1000,0,0,0,1,0,1,0,0,0,0,"/a-new-page","EN: A new page in workspace"
+,10000,0,0,0,0,1,1000,0,0,0,0,,"/","ACME Global modified in Workspace 1"
+,10001,1320,0,0,0,1,1333,4,0,0,0,,"/risk","EN: Risk"
+,10002,1000,0,0,0,2,1300,2,0,0,0,,"/products","EN: Products"
+"sys_refindex"
+,"hash","tablename","recuid","field","flexpointer","softref_key","softref_id","sorting","workspace","ref_table","ref_uid","ref_string"
+,"d82e8687cecaf87aef30a619370d74c9","pages",1101,"l10n_parent",,,,0,0,"pages",1100,
+,"83405f026c17228bef16c5eb0e4349c6","pages",1102,"l10n_parent",,,,0,0,"pages",1100,
diff --git a/typo3/sysext/core/Tests/Functional/Utility/RootlineUtilityTest.php b/typo3/sysext/core/Tests/Functional/Utility/RootlineUtilityTest.php
index b2e593ada54104128d0f6ef11cfc5a0ae8926760..14d8932b562b906662b0b9036c27f45f335637cb 100644
--- a/typo3/sysext/core/Tests/Functional/Utility/RootlineUtilityTest.php
+++ b/typo3/sysext/core/Tests/Functional/Utility/RootlineUtilityTest.php
@@ -18,15 +18,17 @@ declare(strict_types=1);
 namespace TYPO3\CMS\Core\Tests\Functional\Utility;
 
 use PHPUnit\Framework\Attributes\Test;
+use TYPO3\CMS\Core\Cache\Frontend\NullFrontend;
 use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\LanguageAspect;
+use TYPO3\CMS\Core\Context\VisibilityAspect;
 use TYPO3\CMS\Core\Context\WorkspaceAspect;
-use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Database\ReferenceIndex;
+use TYPO3\CMS\Core\Domain\Repository\PageRepository;
 use TYPO3\CMS\Core\Exception\Page\PageNotFoundException;
 use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\RootlineUtility;
-use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
-use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
 
 final class RootlineUtilityTest extends FunctionalTestCase
@@ -45,7 +47,6 @@ final class RootlineUtilityTest extends FunctionalTestCase
     protected function setUp(): void
     {
         parent::setUp();
-
         $this->writeSiteConfiguration(
             'main',
             $this->buildSiteConfiguration(1000, 'https://acme.com/'),
@@ -55,51 +56,296 @@ final class RootlineUtilityTest extends FunctionalTestCase
                 $this->buildLanguageConfiguration('FR-CA', '/fr-ca/', ['FR', 'EN']),
             ]
         );
-        $this->withDatabaseSnapshot(function () {
-            $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
-            $backendUser = $this->setUpBackendUser(1);
-            Bootstrap::initializeLanguageObject();
-            $factory = DataHandlerFactory::fromYamlFile(__DIR__ . '/Fixtures/RootlineScenario.yaml');
-            $writer = DataHandlerWriter::withBackendUser($backendUser);
-            $writer->invokeFactory($factory);
-            static::failIfArrayIsNotEmpty($writer->getErrors());
-        });
+        self::importCSVDataSet(__DIR__ . '/Fixtures/RootlineUtilityImport.csv');
+    }
+
+    private function filterExpectedValues(array $incomingData, array $fields): array
+    {
+        $result = [];
+        foreach ($incomingData as $pos => $values) {
+            $filteredValues = [];
+            foreach ($fields as $field) {
+                if (isset($values[$field])) {
+                    $filteredValues[$field] = $values[$field];
+                }
+            }
+            $result[$pos] = $filteredValues;
+        }
+        return $result;
     }
 
     #[Test]
-    public function getForRootPageOnlyReturnsRootPageInformation(): void
+    public function verifyCleanReferenceIndex()
     {
-        $rootPageUid = 1000;
-        $subject = new RootlineUtility($rootPageUid);
+        $referenceIndexFixResult = GeneralUtility::makeInstance(ReferenceIndex::class)->updateIndex(true);
+        if (count($referenceIndexFixResult['errors']) > 0) {
+            self::fail('Reference index not clean. ' . LF . implode(LF, $referenceIndexFixResult['errors']));
+        }
+    }
 
-        $result = $subject->get();
+    #[Test]
+    public function isMountedPageWithoutMountPointsReturnsFalse(): void
+    {
+        $subject = new RootlineUtility(1, '', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'isMountedPage'));
+        self::assertFalse($subjectMethodReflection->invoke($subject));
+    }
 
-        self::assertCount(1, $result);
-        self::assertSame($rootPageUid, (int)$result[0]['uid']);
+    #[Test]
+    public function isMountedPageWithMatchingMountPointParameterReturnsTrue(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'isMountedPage'));
+        self::assertTrue($subjectMethodReflection->invoke($subject));
     }
 
     #[Test]
-    public function getForRootPageAndWithMissingTableColumnsTcaReturnsEmptyArray(): void
+    public function isMountedPageWithNonMatchingMountPointParameterReturnsFalse(): void
     {
-        $rootPageUid = 1000;
-        $subject = new RootlineUtility($rootPageUid);
+        $subject = new RootlineUtility(1, '99-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'isMountedPage'));
+        self::assertFalse($subjectMethodReflection->invoke($subject));
+    }
 
-        unset($GLOBALS['TCA']['pages']['columns']);
-        $result = $subject->get();
+    #[Test]
+    public function processMountedPageWithNonMountedPageThrowsException(): void
+    {
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionCode(1343464100);
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
+        $subjectMethodReflection->invoke($subject, ['uid' => 1], ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_DEFAULT]);
+    }
 
-        self::assertCount(1, $result);
-        self::assertSame($rootPageUid, (int)$result[0]['uid']);
+    #[Test]
+    public function processMountedPageWithMountedPageNotThrowsException(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
+        $result = $subjectMethodReflection->invoke(
+            $subject,
+            ['uid' => 1],
+            ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
+        );
+        self::assertNotEmpty($result);
     }
 
     #[Test]
-    public function getForRootPageAndWithNonArrayTableColumnsTcaReturnsEmptyArray(): void
+    public function processMountedPageWithMountedPageAddsMountedFromParameter(): void
     {
-        $rootPageUid = 1000;
-        $subject = new RootlineUtility($rootPageUid);
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
+        $result = $subjectMethodReflection->invoke(
+            $subject,
+            ['uid' => 1],
+            ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
+        );
+        self::assertTrue(isset($result['_MOUNTED_FROM']));
+        self::assertSame(1, $result['_MOUNTED_FROM']);
+    }
+
+    #[Test]
+    public function processMountedPageWithMountedPageAddsMountPointParameterToReturnValue(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
+        $result = $subjectMethodReflection->invoke(
+            $subject,
+            ['uid' => 1],
+            ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
+        );
+        self::assertTrue(isset($result['_MP_PARAM']));
+        self::assertSame('1-99', $result['_MP_PARAM']);
+    }
+
+    #[Test]
+    public function processMountedPageForMountPageIsOverlayAddsMountOLParameter(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
+        $result = $subjectMethodReflection->invoke(
+            $subject,
+            ['uid' => 1],
+            ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1, 'mount_pid_ol' => 1]
+        );
+        self::assertTrue(isset($result['_MOUNT_OL']));
+        self::assertTrue($result['_MOUNT_OL']);
+    }
+
+    #[Test]
+    public function processMountedPageForMountPageIsOverlayAddsDataInformationAboutMountPage(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
+        $result = $subjectMethodReflection->invoke(
+            $subject,
+            ['uid' => 1],
+            [
+                'uid' => 99,
+                'doktype' => PageRepository::DOKTYPE_MOUNTPOINT,
+                'mount_pid' => 1,
+                'mount_pid_ol' => 1,
+                'pid' => 5,
+                'title' => 'TestCase',
+            ]
+        );
+        self::assertTrue(isset($result['_MOUNT_PAGE']));
+        self::assertSame(['uid' => 99, 'pid' => 5, 'title' => 'TestCase'], $result['_MOUNT_PAGE']);
+    }
+
+    #[Test]
+    public function processMountedPageForMountPageWithoutOverlayReplacesMountedPageWithMountPage(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
+        $mountPointPageData = [
+            'uid' => 99,
+            'doktype' => PageRepository::DOKTYPE_MOUNTPOINT,
+            'mount_pid' => 1,
+            'mount_pid_ol' => 0,
+        ];
+        $result = $subjectMethodReflection->invoke(
+            $subject,
+            ['uid' => 1],
+            $mountPointPageData
+        );
+        // Tests that $mountPointPageData is completely part of $result and keys match.
+        self::assertSame($mountPointPageData, array_intersect_assoc($mountPointPageData, $result));
+    }
+
+    #[Test]
+    public function columnHasRelationToResolveDetectsGroupFieldAsLocal(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
+        self::assertFalse($subjectMethodReflection->invoke(
+            $subject,
+            [
+                'config' => [
+                    'type' => 'group',
+                ],
+            ]
+        ));
+    }
+
+    #[Test]
+    public function columnHasRelationToResolveDetectsGroupFieldWithMMAsRemote(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
+        self::assertTrue($subjectMethodReflection->invoke(
+            $subject,
+            [
+                'config' => [
+                    'type' => 'group',
+                    'MM' => 'tx_xyz',
+                ],
+            ]
+        ));
+    }
+
+    #[Test]
+    public function columnHasRelationToResolveDetectsInlineFieldAsLocal(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
+        self::assertFalse($subjectMethodReflection->invoke(
+            $subject,
+            [
+                'config' => [
+                    'type' => 'inline',
+                ],
+            ]
+        ));
+    }
+
+    #[Test]
+    public function columnHasRelationToResolveDetectsInlineFieldWithForeignKeyAsRemote(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
+        self::assertTrue($subjectMethodReflection->invoke(
+            $subject,
+            [
+                'config' => [
+                    'type' => 'inline',
+                    'foreign_field' => 'xyz',
+                ],
+            ]
+        ));
+    }
+
+    #[Test]
+    public function columnHasRelationToResolveDetectsInlineFieldWithFMMAsRemote(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
+        self::assertTrue($subjectMethodReflection->invoke(
+            $subject,
+            [
+                'config' => [
+                    'type' => 'inline',
+                    'MM' => 'xyz',
+                ],
+            ]
+        ));
+    }
+
+    #[Test]
+    public function columnHasRelationToResolveDetectsSelectFieldAsLocal(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
+        self::assertFalse($subjectMethodReflection->invoke(
+            $subject,
+            [
+                'config' => [
+                    'type' => 'select',
+                ],
+            ]
+        ));
+    }
 
-        $GLOBALS['TCA']['pages']['columns'] = 'This is not an array.';
-        $result = $subject->get();
+    #[Test]
+    public function columnHasRelationToResolveDetectsSelectFieldWithMMAsRemote(): void
+    {
+        $subject = new RootlineUtility(1, '1-99', new Context());
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
+        self::assertTrue($subjectMethodReflection->invoke(
+            $subject,
+            [
+                'config' => [
+                    'type' => 'select',
+                    'MM' => 'xyz',
+                ],
+            ]
+        ));
+    }
 
+    #[Test]
+    public function getCacheIdentifierContainsAllContextParameters(): void
+    {
+        $cacheFrontend = new NullFrontend('some-frontend');
+        $context = new Context();
+        $context->setAspect('workspace', new WorkspaceAspect(15));
+        $context->setAspect('visibility', new VisibilityAspect(true));
+        $context->setAspect('language', new LanguageAspect(8, 8, LanguageAspect::OVERLAYS_OFF));
+        $subject = new RootlineUtility(42, '47-11', $context);
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'getCacheIdentifier'));
+        self::assertSame('42_47-11_8_15_0_1', $subjectMethodReflection->invoke($subject));
+        self::assertTrue($cacheFrontend->isValidEntryIdentifier($subjectMethodReflection->invoke($subject)));
+        $context->setAspect('workspace', new WorkspaceAspect(0));
+        $subject = new RootlineUtility(42, '47-11', $context);
+        $subjectMethodReflection = (new \ReflectionMethod($subject, 'getCacheIdentifier'));
+        self::assertSame('42_47-11_8_0_0_1', $subjectMethodReflection->invoke($subject));
+        self::assertTrue($cacheFrontend->isValidEntryIdentifier($subjectMethodReflection->invoke($subject)));
+    }
+
+    #[Test]
+    public function getForRootPageOnlyReturnsRootPageInformation(): void
+    {
+        $rootPageUid = 1000;
+        $result = (new RootlineUtility($rootPageUid))->get();
         self::assertCount(1, $result);
         self::assertSame($rootPageUid, (int)$result[0]['uid']);
     }
@@ -107,11 +353,9 @@ final class RootlineUtilityTest extends FunctionalTestCase
     #[Test]
     public function resolveLivePagesAndSkipWorkspacedVersions(): void
     {
-        $context = GeneralUtility::makeInstance(Context::class);
+        $context = new Context();
         $context->setAspect('workspace', new WorkspaceAspect(0));
-        $subject = new RootlineUtility(1330, '', $context);
-        $result = $subject->get();
-
+        $result = (new RootlineUtility(1330, '', $context))->get();
         $expected = [
             2 => [
                 'pid' => 1300,
@@ -144,11 +388,9 @@ final class RootlineUtilityTest extends FunctionalTestCase
     #[Test]
     public function resolveWorkspaceOverlaysOfNewPageInWorkspace(): void
     {
-        $context = GeneralUtility::makeInstance(Context::class);
+        $context = new Context();
         $context->setAspect('workspace', new WorkspaceAspect(1));
-        $subject = new RootlineUtility(1400, '', $context);
-        $result = $subject->get();
-
+        $result = (new RootlineUtility(1400, '', $context))->get();
         $expected = [
             1 => [
                 'pid' => 1000,
@@ -174,11 +416,9 @@ final class RootlineUtilityTest extends FunctionalTestCase
     #[Test]
     public function resolveLiveRootLineForMovedPage(): void
     {
-        $context = GeneralUtility::makeInstance(Context::class);
+        $context = new Context();
         $context->setAspect('workspace', new WorkspaceAspect(0));
-        $subject = new RootlineUtility(1333, '', $context);
-        $result = $subject->get();
-
+        $result = (new RootlineUtility(1333, '', $context))->get();
         $expected = [
             3 => [
                 'pid' => 1330,
@@ -219,11 +459,9 @@ final class RootlineUtilityTest extends FunctionalTestCase
     #[Test]
     public function resolveWorkspaceOverlaysOfMovedPage(): void
     {
-        $context = GeneralUtility::makeInstance(Context::class);
+        $context = new Context();
         $context->setAspect('workspace', new WorkspaceAspect(1));
-        $subject = new RootlineUtility(1333, '', $context);
-        $result = $subject->get();
-
+        $result = (new RootlineUtility(1333, '', $context))->get();
         $expected = [
             3 => [
                 'pid' => 1320,
@@ -232,8 +470,8 @@ final class RootlineUtilityTest extends FunctionalTestCase
                 't3ver_wsid' => 1,
                 't3ver_state' => 4,
                 'title' => 'EN: Risk',
-                '_ORIG_pid' => 1330, // Pointing to the LIVE pid! WHY? All others point to the same PID! @todo
                 '_ORIG_uid' => 10001,
+                '_ORIG_pid' => 1330, // Pointing to the LIVE pid! WHY? All others point to the same PID! @todo
             ],
             2 => [
                 'pid' => 1300,
@@ -264,8 +502,7 @@ final class RootlineUtilityTest extends FunctionalTestCase
         self::assertSame($expected, $this->filterExpectedValues($result, ['pid', 'uid', 't3ver_oid', 't3ver_wsid', 't3ver_state', 'title', '_ORIG_uid', '_ORIG_pid']));
 
         // Now explicitly requesting the versioned ID, which holds the same result
-        $subject = new RootlineUtility(10001, '', $context);
-        $result = $subject->get();
+        $result = (new RootlineUtility(10001, '', $context))->get();
         self::assertSame($expected, $this->filterExpectedValues($result, ['pid', 'uid', 't3ver_oid', 't3ver_wsid', 't3ver_state', 'title', '_ORIG_uid', '_ORIG_pid']));
     }
 
@@ -274,25 +511,8 @@ final class RootlineUtilityTest extends FunctionalTestCase
     {
         $this->expectException(PageNotFoundException::class);
         $this->expectExceptionCode(1343464101);
-        $context = GeneralUtility::makeInstance(Context::class);
+        $context = new Context();
         $context->setAspect('workspace', new WorkspaceAspect(2));
-        $subject = new RootlineUtility(1310, '', $context);
-        $subject->get();
-    }
-
-    protected function filterExpectedValues(array $incomingData, array $fields): array
-    {
-        $result = [];
-        foreach ($incomingData as $pos => $values) {
-            array_walk($values, static function (&$val) {
-                if (is_numeric($val)) {
-                    $val = (int)$val;
-                }
-            });
-            $result[$pos] = array_filter($values, static function ($fieldName) use ($fields) {
-                return in_array($fieldName, $fields, true);
-            }, ARRAY_FILTER_USE_KEY);
-        }
-        return $result;
+        (new RootlineUtility(1310, '', $context))->get();
     }
 }
diff --git a/typo3/sysext/core/Tests/Unit/Utility/RootlineUtilityTest.php b/typo3/sysext/core/Tests/Unit/Utility/RootlineUtilityTest.php
deleted file mode 100644
index f09e01bb333dc70d2d9652d032230ebf5c807f6e..0000000000000000000000000000000000000000
--- a/typo3/sysext/core/Tests/Unit/Utility/RootlineUtilityTest.php
+++ /dev/null
@@ -1,291 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-namespace TYPO3\CMS\Core\Tests\Unit\Utility;
-
-use PHPUnit\Framework\Attributes\Test;
-use PHPUnit\Framework\MockObject\MockObject;
-use TYPO3\CMS\Core\Cache\CacheManager;
-use TYPO3\CMS\Core\Cache\Frontend\NullFrontend;
-use TYPO3\CMS\Core\Context\Context;
-use TYPO3\CMS\Core\Context\LanguageAspect;
-use TYPO3\CMS\Core\Context\VisibilityAspect;
-use TYPO3\CMS\Core\Context\WorkspaceAspect;
-use TYPO3\CMS\Core\Domain\Repository\PageRepository;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\RootlineUtility;
-use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
-use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
-
-final class RootlineUtilityTest extends UnitTestCase
-{
-    protected RootlineUtility&MockObject&AccessibleObjectInterface $subject;
-
-    protected function setUp(): void
-    {
-        parent::setUp();
-        $cacheManager = new CacheManager();
-        $cacheManager->registerCache(new NullFrontend('rootline'));
-        $cacheManager->registerCache(new NullFrontend('runtime'));
-        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManager);
-
-        $this->subject = $this->getAccessibleMock(
-            RootlineUtility::class,
-            ['enrichWithRelationFields', 'resolvePageId'],
-            [1, '', new Context()]
-        );
-
-        $this->subject->method('resolvePageId')->willReturnArgument(0);
-    }
-
-    protected function tearDown(): void
-    {
-        GeneralUtility::purgeInstances();
-        parent::tearDown();
-    }
-
-    /**
-     * Tests that $subsetCandidate is completely part of $superset
-     * and keys match.
-     *
-     * See (A ^ B) = A <=> A c B
-     * @param array $subsetCandidate
-     * @param array $superset
-     */
-    protected function assertIsSubset(array $subsetCandidate, array $superset): void
-    {
-        self::assertSame($subsetCandidate, array_intersect_assoc($subsetCandidate, $superset));
-    }
-
-    #[Test]
-    public function isMountedPageWithoutMountPointsReturnsFalse(): void
-    {
-        $this->subject->__construct(1, '', new Context());
-        self::assertFalse($this->subject->isMountedPage());
-    }
-
-    #[Test]
-    public function isMountedPageWithMatchingMountPointParameterReturnsTrue(): void
-    {
-        $this->subject->__construct(1, '1-99', new Context());
-        self::assertTrue($this->subject->isMountedPage());
-    }
-
-    #[Test]
-    public function isMountedPageWithNonMatchingMountPointParameterReturnsFalse(): void
-    {
-        $this->subject->__construct(1, '99-99', new Context());
-        self::assertFalse($this->subject->isMountedPage());
-    }
-
-    #[Test]
-    public function processMountedPageWithNonMountedPageThrowsException(): void
-    {
-        $this->expectException(\RuntimeException::class);
-        $this->expectExceptionCode(1343464100);
-
-        $this->subject->__construct(1, '1-99', new Context());
-        $this->subject->_call(
-            'processMountedPage',
-            ['uid' => 1],
-            ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_DEFAULT]
-        );
-    }
-
-    #[Test]
-    public function processMountedPageWithMountedPageNotThrowsException(): void
-    {
-        $this->subject->__construct(1, '1-99', new Context());
-        self::assertNotEmpty($this->subject->_call(
-            'processMountedPage',
-            ['uid' => 1],
-            ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
-        ));
-    }
-
-    #[Test]
-    public function processMountedPageWithMountedPageAddsMountedFromParameter(): void
-    {
-        $this->subject->__construct(1, '1-99', new Context());
-        $result = $this->subject->_call(
-            'processMountedPage',
-            ['uid' => 1],
-            ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
-        );
-        self::assertTrue(isset($result['_MOUNTED_FROM']));
-        self::assertSame(1, $result['_MOUNTED_FROM']);
-    }
-
-    #[Test]
-    public function processMountedPageWithMountedPageAddsMountPointParameterToReturnValue(): void
-    {
-        $this->subject->__construct(1, '1-99', new Context());
-        $result = $this->subject->_call(
-            'processMountedPage',
-            ['uid' => 1],
-            ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
-        );
-        self::assertTrue(isset($result['_MP_PARAM']));
-        self::assertSame('1-99', $result['_MP_PARAM']);
-    }
-
-    #[Test]
-    public function processMountedPageForMountPageIsOverlayAddsMountOLParameter(): void
-    {
-        $this->subject->__construct(1, '1-99', new Context());
-        $result = $this->subject->_call(
-            'processMountedPage',
-            ['uid' => 1],
-            ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1, 'mount_pid_ol' => 1]
-        );
-        self::assertTrue(isset($result['_MOUNT_OL']));
-        self::assertTrue($result['_MOUNT_OL']);
-    }
-
-    #[Test]
-    public function processMountedPageForMountPageIsOverlayAddsDataInformationAboutMountPage(): void
-    {
-        $this->subject->__construct(1, '1-99', new Context());
-        $result = $this->subject->_call('processMountedPage', ['uid' => 1], [
-            'uid' => 99,
-            'doktype' => PageRepository::DOKTYPE_MOUNTPOINT,
-            'mount_pid' => 1,
-            'mount_pid_ol' => 1,
-            'pid' => 5,
-            'title' => 'TestCase',
-        ]);
-        self::assertTrue(isset($result['_MOUNT_PAGE']));
-        self::assertSame(['uid' => 99, 'pid' => 5, 'title' => 'TestCase'], $result['_MOUNT_PAGE']);
-    }
-
-    #[Test]
-    public function processMountedPageForMountPageWithoutOverlayReplacesMountedPageWithMountPage(): void
-    {
-        $mountPointPageData = [
-            'uid' => 99,
-            'doktype' => PageRepository::DOKTYPE_MOUNTPOINT,
-            'mount_pid' => 1,
-            'mount_pid_ol' => 0,
-        ];
-        $this->subject->__construct(1, '1-99', new Context());
-        $result = $this->subject->_call('processMountedPage', ['uid' => 1], $mountPointPageData);
-        $this->assertIsSubset($mountPointPageData, $result);
-    }
-
-    #[Test]
-    public function columnHasRelationToResolveDetectsGroupFieldAsLocal(): void
-    {
-        self::assertFalse($this->subject->_call('columnHasRelationToResolve', [
-            'type' => 'group',
-        ]));
-    }
-
-    #[Test]
-    public function columnHasRelationToResolveDetectsGroupFieldWithMMAsRemote2(): void
-    {
-        self::assertTrue($this->subject->_call('columnHasRelationToResolve', [
-            'config' => [
-                'type' => 'group',
-                'MM' => 'tx_xyz',
-            ],
-        ]));
-    }
-
-    #[Test]
-    public function columnHasRelationToResolveDetectsInlineFieldAsLocal(): void
-    {
-        self::assertFalse($this->subject->_call('columnHasRelationToResolve', [
-            'config' => [
-                'type' => 'inline',
-            ],
-        ]));
-    }
-
-    #[Test]
-    public function columnHasRelationToResolveDetectsInlineFieldWithForeignKeyAsRemote(): void
-    {
-        self::assertTrue($this->subject->_call('columnHasRelationToResolve', [
-            'config' => [
-                'type' => 'inline',
-                'foreign_field' => 'xyz',
-            ],
-        ]));
-    }
-
-    #[Test]
-    public function columnHasRelationToResolveDetectsInlineFieldWithFMMAsRemote(): void
-    {
-        self::assertTrue($this->subject->_call('columnHasRelationToResolve', [
-            'config' => [
-                'type' => 'inline',
-                'MM' => 'xyz',
-            ],
-        ]));
-    }
-
-    #[Test]
-    public function columnHasRelationToResolveDetectsSelectFieldAsLocal(): void
-    {
-        self::assertFalse($this->subject->_call('columnHasRelationToResolve', [
-            'config' => [
-                'type' => 'select',
-            ],
-        ]));
-    }
-
-    #[Test]
-    public function columnHasRelationToResolveDetectsSelectFieldWithMMAsRemote(): void
-    {
-        self::assertTrue($this->subject->_call('columnHasRelationToResolve', [
-            'config' => [
-                'type' => 'select',
-                'MM' => 'xyz',
-            ],
-        ]));
-    }
-
-    #[Test]
-    public function getCacheIdentifierContainsAllContextParameters(): void
-    {
-        $this->subject->method('resolvePageId')->willReturn(42);
-
-        $context = new Context();
-        $context->setAspect('workspace', new WorkspaceAspect(15));
-        $context->setAspect('visibility', new VisibilityAspect(true));
-        $context->setAspect('language', new LanguageAspect(8, 8, LanguageAspect::OVERLAYS_OFF));
-        $this->subject->__construct(42, '47-11', $context);
-        self::assertSame('42_47-11_8_15_0_1', $this->subject->getCacheIdentifier());
-        $this->subject->__construct(42, '47-11', $context);
-        self::assertSame('42_47-11_8_15_0_1', $this->subject->getCacheIdentifier());
-
-        $context->setAspect('workspace', new WorkspaceAspect(0));
-        $this->subject->__construct(42, '47-11', $context);
-        self::assertSame('42_47-11_8_0_0_1', $this->subject->getCacheIdentifier());
-    }
-
-    #[Test]
-    public function getCacheIdentifierReturnsValidIdentifierWithCommasInMountPointParameter(): void
-    {
-        $this->subject->method('resolvePageId')->willReturn(42);
-        $cacheFrontend = new NullFrontend('some-frontend');
-        $context = new Context();
-        $context->setAspect('workspace', new WorkspaceAspect(15));
-        $context->setAspect('language', new LanguageAspect(8, 8, LanguageAspect::OVERLAYS_OFF));
-        $this->subject->__construct(42, '47-11,48-12', $context);
-        self::assertTrue($cacheFrontend->isValidEntryIdentifier($this->subject->getCacheIdentifier()));
-    }
-}