diff --git a/core/.phpstan-baseline.php b/core/.phpstan-baseline.php
index a4b7ee050fb087535b9724dc0d5522ddeaa17135..65d42970126e94b98930dd6fe18ef268b28c52cb 100644
--- a/core/.phpstan-baseline.php
+++ b/core/.phpstan-baseline.php
@@ -30391,12 +30391,6 @@
 	'count' => 1,
 	'path' => __DIR__ . '/modules/node/src/Routing/RouteSubscriber.php',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Function node_access_test_add_field\\(\\) has no return type specified\\.$#',
-	'identifier' => 'missingType.return',
-	'count' => 1,
-	'path' => __DIR__ . '/modules/node/tests/modules/node_access_test/node_access_test.module',
-];
 $ignoreErrors[] = [
 	'message' => '#^Method Drupal\\\\node_test\\\\Hook\\\\NodeTestHooks\\:\\:nodeInsert\\(\\) has no return type specified\\.$#',
 	'identifier' => 'missingType.return',
diff --git a/core/modules/content_moderation/tests/src/Functional/NodeAccessTest.php b/core/modules/content_moderation/tests/src/Functional/NodeAccessTest.php
index e9b9f9e6007f3798ab643028b860917d86db6b94..d8da46eea314413e03c0563da64157e69f039e2d 100644
--- a/core/modules/content_moderation/tests/src/Functional/NodeAccessTest.php
+++ b/core/modules/content_moderation/tests/src/Functional/NodeAccessTest.php
@@ -5,6 +5,7 @@
 namespace Drupal\Tests\content_moderation\Functional;
 
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 
 /**
  * Tests permission access control around nodes.
@@ -13,6 +14,8 @@
  */
 class NodeAccessTest extends ModerationStateTestBase {
 
+  use NodeAccessTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -60,7 +63,7 @@ protected function setUp(): void {
     $this->grantUserPermissionToCreateContentOfType($this->adminUser, 'moderated_content');
 
     // Add the private field to the node type.
-    node_access_test_add_field(NodeType::load('moderated_content'));
+    $this->addPrivateField(NodeType::load('moderated_content'));
 
     // Rebuild permissions because hook_node_grants() is implemented by the
     // node_access_test_empty module.
diff --git a/core/modules/field_ui/tests/src/Functional/ManageFieldsFunctionalTestBase.php b/core/modules/field_ui/tests/src/Functional/ManageFieldsFunctionalTestBase.php
index 2d47412fec755a96a13e6257c7f4253d88e71d3b..360e1f8ffa66f9a4c1b3628503082d4f090d95f3 100644
--- a/core/modules/field_ui/tests/src/Functional/ManageFieldsFunctionalTestBase.php
+++ b/core/modules/field_ui/tests/src/Functional/ManageFieldsFunctionalTestBase.php
@@ -6,6 +6,7 @@
 
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 use Drupal\taxonomy\Entity\Vocabulary;
 use Drupal\Tests\BrowserTestBase;
 use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait;
@@ -16,8 +17,9 @@
  */
 class ManageFieldsFunctionalTestBase extends BrowserTestBase {
 
-  use FieldUiTestTrait;
   use EntityReferenceFieldCreationTrait;
+  use FieldUiTestTrait;
+  use NodeAccessTrait;
 
   /**
    * {@inheritdoc}
@@ -136,7 +138,7 @@ protected function setUp(): void {
 
     // Setup node access testing.
     node_access_rebuild();
-    node_access_test_add_field(NodeType::load('article'));
+    $this->addPrivateField(NodeType::load('article'));
     \Drupal::state()->set('node_access_test.private', TRUE);
 
   }
diff --git a/core/modules/file/tests/src/Functional/FilePrivateTest.php b/core/modules/file/tests/src/Functional/FilePrivateTest.php
index b7d2d7a4de21984d2cbe6fadd4729623d754e7d9..3eb1fe5486166119926eab0bed9800e2ea18855e 100644
--- a/core/modules/file/tests/src/Functional/FilePrivateTest.php
+++ b/core/modules/file/tests/src/Functional/FilePrivateTest.php
@@ -6,6 +6,7 @@
 
 use Drupal\file\Entity\File;
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 use Drupal\user\RoleInterface;
 
 /**
@@ -15,6 +16,8 @@
  */
 class FilePrivateTest extends FileFieldTestBase {
 
+  use NodeAccessTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -30,7 +33,7 @@ class FilePrivateTest extends FileFieldTestBase {
    */
   protected function setUp(): void {
     parent::setUp();
-    node_access_test_add_field(NodeType::load('article'));
+    $this->addPrivateField(NodeType::load('article'));
     node_access_rebuild();
     \Drupal::state()->set('node_access_test.private', TRUE);
     // This test expects unused managed files to be marked as a temporary file.
diff --git a/core/modules/node/tests/modules/node_access_test/node_access_test.module b/core/modules/node/tests/modules/node_access_test/node_access_test.module
deleted file mode 100644
index e6af0dbe82add2acb8d6f12add44b7edbcb79e66..0000000000000000000000000000000000000000
--- a/core/modules/node/tests/modules/node_access_test/node_access_test.module
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-/**
- * @file
- * Test module for testing the node access system.
- *
- * This module's functionality depends on the following state variables:
- * - node_access_test.no_access_uid: Used in NodeQueryAlterTest to enable the
- *   node_access_all grant realm.
- * - node_access_test.private: When TRUE, the module controls access for nodes
- *   with a 'private' property set, and inherits the default core access for
- *   nodes without this flag. When FALSE, the module controls access for all
- *   nodes.
- * - node_access_test_secret_catalan: When set to TRUE and using the Catalan
- *   'ca' language code, makes all Catalan content secret.
- *
- * @see node_access_test_node_grants()
- * @see \Drupal\node\Tests\NodeQueryAlterTest
- * @see \Drupal\node\Tests\NodeAccessBaseTableTest
- */
-
-declare(strict_types=1);
-
-use Drupal\field\Entity\FieldStorageConfig;
-use Drupal\field\Entity\FieldConfig;
-use Drupal\node\NodeTypeInterface;
-
-/**
- * Adds the private field to a node type.
- *
- * @param \Drupal\node\NodeTypeInterface $type
- *   A node type entity.
- */
-function node_access_test_add_field(NodeTypeInterface $type) {
-  $field_storage = FieldStorageConfig::create([
-    'field_name' => 'private',
-    'entity_type' => 'node',
-    'type' => 'integer',
-  ]);
-  $field_storage->save();
-  $field = FieldConfig::create([
-    'field_name' => 'private',
-    'entity_type' => 'node',
-    'bundle' => $type->id(),
-    'label' => 'Private',
-  ]);
-  $field->save();
-
-  // Assign widget settings for the 'default' form mode.
-  \Drupal::service('entity_display.repository')
-    ->getFormDisplay('node', $type->id())
-    ->setComponent('private', [
-      'type' => 'number',
-    ])
-    ->save();
-}
diff --git a/core/modules/node/tests/src/Functional/NodeAccessBaseTableTest.php b/core/modules/node/tests/src/Functional/NodeAccessBaseTableTest.php
index a677bd29f3168244f8bfc56abfe544376fd31b02..2e584f3b8260d904329cb0f053d5d3cc9dd06639 100644
--- a/core/modules/node/tests/src/Functional/NodeAccessBaseTableTest.php
+++ b/core/modules/node/tests/src/Functional/NodeAccessBaseTableTest.php
@@ -7,6 +7,7 @@
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 use Drupal\taxonomy\Entity\Vocabulary;
 use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait;
 
@@ -18,6 +19,7 @@
 class NodeAccessBaseTableTest extends NodeTestBase {
 
   use EntityReferenceFieldCreationTrait;
+  use NodeAccessTrait;
 
   /**
    * {@inheritdoc}
@@ -102,7 +104,7 @@ protected function setUp(): void {
       ])
       ->save();
 
-    node_access_test_add_field(NodeType::load('article'));
+    $this->addPrivateField(NodeType::load('article'));
 
     node_access_rebuild();
     \Drupal::state()->set('node_access_test.private', TRUE);
diff --git a/core/modules/node/tests/src/Functional/NodeAccessJoinTest.php b/core/modules/node/tests/src/Functional/NodeAccessJoinTest.php
index fe6a8ed12f0911ec4d22c51b2b312391f471c66a..6b76c947115286df90b893aee5779bcd82a43ba6 100644
--- a/core/modules/node/tests/src/Functional/NodeAccessJoinTest.php
+++ b/core/modules/node/tests/src/Functional/NodeAccessJoinTest.php
@@ -7,6 +7,7 @@
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 use Drupal\user\UserInterface;
 use Drupal\views\Tests\ViewTestData;
 
@@ -17,6 +18,8 @@
  */
 class NodeAccessJoinTest extends NodeTestBase {
 
+  use NodeAccessTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -75,7 +78,7 @@ class NodeAccessJoinTest extends NodeTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    node_access_test_add_field(NodeType::load('article'));
+    $this->addPrivateField(NodeType::load('article'));
 
     $field_storage = FieldStorageConfig::create([
       'field_name' => 'related_article',
diff --git a/core/modules/node/tests/src/Functional/NodeAccessRebuildNodeGrantsTest.php b/core/modules/node/tests/src/Functional/NodeAccessRebuildNodeGrantsTest.php
index 5d8a68a37b022c59adf49a8b9a4511c50e91f5a2..da9dccecef041832afa69493a7925af09c2adbf1 100644
--- a/core/modules/node/tests/src/Functional/NodeAccessRebuildNodeGrantsTest.php
+++ b/core/modules/node/tests/src/Functional/NodeAccessRebuildNodeGrantsTest.php
@@ -5,6 +5,7 @@
 namespace Drupal\Tests\node\Functional;
 
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 
 /**
  * Tests node access rebuild functions with multiple node access modules.
@@ -13,6 +14,8 @@
  */
 class NodeAccessRebuildNodeGrantsTest extends NodeTestBase {
 
+  use NodeAccessTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -55,7 +58,7 @@ protected function setUp(): void {
   public function testNodeAccessRebuildNodeGrants(): void {
     \Drupal::service('module_installer')->install(['node_access_test']);
     \Drupal::state()->set('node_access_test.private', TRUE);
-    node_access_test_add_field(NodeType::load('page'));
+    $this->addPrivateField(NodeType::load('page'));
     $this->resetAll();
 
     // Create 30 nodes so that _node_access_rebuild_batch_operation() has to run
diff --git a/core/modules/node/tests/src/Functional/Views/BulkFormAccessTest.php b/core/modules/node/tests/src/Functional/Views/BulkFormAccessTest.php
index d430510f2802ed6bb9d8f9bb77af70ee456d0a9a..664d57028dd2ba5658d8276d9968640c85e46ebd 100644
--- a/core/modules/node/tests/src/Functional/Views/BulkFormAccessTest.php
+++ b/core/modules/node/tests/src/Functional/Views/BulkFormAccessTest.php
@@ -6,6 +6,7 @@
 
 use Drupal\node\Entity\Node;
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 
 /**
  * Tests if entity access is respected on a node bulk operations form.
@@ -18,6 +19,8 @@
  */
 class BulkFormAccessTest extends NodeTestBase {
 
+  use NodeAccessTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -53,7 +56,7 @@ protected function setUp($import_test_views = TRUE, $modules = ['node_test_views
 
     $this->accessHandler = \Drupal::entityTypeManager()->getAccessControlHandler('node');
 
-    node_access_test_add_field(NodeType::load('article'));
+    $this->addPrivateField(NodeType::load('article'));
 
     // After enabling a node access module, the access table has to be rebuild.
     node_access_rebuild();
diff --git a/core/modules/node/tests/src/Functional/Views/FilterNodeAccessTest.php b/core/modules/node/tests/src/Functional/Views/FilterNodeAccessTest.php
index 2587f69f6faba3a0c29abef24a4d8ecfeccc45f6..e51519689188d9041348a125c839214599117493 100644
--- a/core/modules/node/tests/src/Functional/Views/FilterNodeAccessTest.php
+++ b/core/modules/node/tests/src/Functional/Views/FilterNodeAccessTest.php
@@ -5,6 +5,7 @@
 namespace Drupal\Tests\node\Functional\Views;
 
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 
 /**
  * Tests the node_access filter handler.
@@ -14,6 +15,8 @@
  */
 class FilterNodeAccessTest extends NodeTestBase {
 
+  use NodeAccessTrait;
+
   /**
    * An array of users.
    *
@@ -46,7 +49,7 @@ protected function setUp($import_test_views = TRUE, $modules = ['node_test_views
 
     $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
 
-    node_access_test_add_field(NodeType::load('article'));
+    $this->addPrivateField(NodeType::load('article'));
 
     node_access_rebuild();
     \Drupal::state()->set('node_access_test.private', TRUE);
diff --git a/core/modules/node/tests/src/Kernel/NodeAccessLanguageAwareCombinationTest.php b/core/modules/node/tests/src/Kernel/NodeAccessLanguageAwareCombinationTest.php
index fc56af9c9ae595b09246f1ecedf6b11acd82f507..b82112c19f044c27edc5334e4f4cc1b82d3e6a9d 100644
--- a/core/modules/node/tests/src/Kernel/NodeAccessLanguageAwareCombinationTest.php
+++ b/core/modules/node/tests/src/Kernel/NodeAccessLanguageAwareCombinationTest.php
@@ -10,6 +10,7 @@
 use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\node\Entity\NodeType;
 use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 
 /**
  * Tests node access with multiple languages and two node access modules.
@@ -18,6 +19,8 @@
  */
 class NodeAccessLanguageAwareCombinationTest extends NodeAccessTestBase {
 
+  use NodeAccessTrait;
+
   /**
    * Enable language and two node access modules.
    *
@@ -56,7 +59,7 @@ class NodeAccessLanguageAwareCombinationTest extends NodeAccessTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    node_access_test_add_field(NodeType::load('page'));
+    $this->addPrivateField(NodeType::load('page'));
 
     // Create the 'private' field, which allows the node to be marked as private
     // (restricted access) in a given translation.
diff --git a/core/modules/node/tests/src/Kernel/NodeAccessLanguageTest.php b/core/modules/node/tests/src/Kernel/NodeAccessLanguageTest.php
index 0c7dd55f006c3a423a84905f8504258590f2e06b..78c34a8bde279eab9dcf49a4246652d9924e435f 100644
--- a/core/modules/node/tests/src/Kernel/NodeAccessLanguageTest.php
+++ b/core/modules/node/tests/src/Kernel/NodeAccessLanguageTest.php
@@ -8,6 +8,7 @@
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 
 /**
  * Tests multilingual node access with a module that is not language-aware.
@@ -16,6 +17,8 @@
  */
 class NodeAccessLanguageTest extends NodeAccessTestBase {
 
+  use NodeAccessTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -27,7 +30,7 @@ class NodeAccessLanguageTest extends NodeAccessTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    node_access_test_add_field(NodeType::load('page'));
+    $this->addPrivateField(NodeType::load('page'));
 
     // After enabling a node access module, the access table has to be rebuild.
     node_access_rebuild();
diff --git a/core/modules/node/tests/src/Traits/NodeAccessTrait.php b/core/modules/node/tests/src/Traits/NodeAccessTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..fff2a5e16d104ecdcd40330a875e6f37d6a426ab
--- /dev/null
+++ b/core/modules/node/tests/src/Traits/NodeAccessTrait.php
@@ -0,0 +1,52 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\node\Traits;
+
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\node\NodeTypeInterface;
+
+/**
+ * Trait for node permission testing.
+ *
+ * This trait is meant to be used only by test classes.
+ */
+trait NodeAccessTrait {
+
+  /**
+   * Adds the private field to a node type.
+   *
+   * @param \Drupal\node\NodeTypeInterface $type
+   *   A node type entity.
+   *
+   * @see \Drupal\node_access_test\Hook\NodeAccessTestHooks::nodeGrants()
+   * @see \Drupal\Tests\node\Functional\NodeQueryAlterTest
+   * @see \Drupal\Tests\node\Functional\NodeAccessBaseTableTest
+   */
+  public function addPrivateField(NodeTypeInterface $type): void {
+    $field_storage = FieldStorageConfig::create([
+      'field_name' => 'private',
+      'entity_type' => 'node',
+      'type' => 'integer',
+    ]);
+    $field_storage->save();
+    $field = FieldConfig::create([
+      'field_name' => 'private',
+      'entity_type' => 'node',
+      'bundle' => $type->id(),
+      'label' => 'Private',
+    ]);
+    $field->save();
+
+    // Assign widget settings for the 'default' form mode.
+    \Drupal::service('entity_display.repository')
+      ->getFormDisplay('node', $type->id())
+      ->setComponent('private', [
+        'type' => 'number',
+      ])
+      ->save();
+  }
+
+}
diff --git a/core/modules/system/tests/src/Functional/Module/PrepareUninstallTest.php b/core/modules/system/tests/src/Functional/Module/PrepareUninstallTest.php
index 664901a1963a7b3f4bc8f225835d20eb1cdd5ffe..b0982f77df75da13c7afcc2b65ed9e5d5679a76f 100644
--- a/core/modules/system/tests/src/Functional/Module/PrepareUninstallTest.php
+++ b/core/modules/system/tests/src/Functional/Module/PrepareUninstallTest.php
@@ -5,6 +5,7 @@
 namespace Drupal\Tests\system\Functional\Module;
 
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 use Drupal\Tests\BrowserTestBase;
 use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;
 
@@ -16,6 +17,7 @@
 class PrepareUninstallTest extends BrowserTestBase {
 
   use TaxonomyTestTrait;
+  use NodeAccessTrait;
 
   /**
    * {@inheritdoc}
@@ -52,7 +54,7 @@ protected function setUp(): void {
 
     $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
     node_access_rebuild();
-    node_access_test_add_field(NodeType::load('article'));
+    $this->addPrivateField(NodeType::load('article'));
     \Drupal::state()->set('node_access_test.private', TRUE);
 
     // Create 10 nodes.
diff --git a/core/modules/user/tests/src/Functional/UserCancelTest.php b/core/modules/user/tests/src/Functional/UserCancelTest.php
index b1a2a0b5067ecb05cf800414a31ed7b10581bcc3..d5bdb788e6a97d78b23305e384dd09fcd6efad42 100644
--- a/core/modules/user/tests/src/Functional/UserCancelTest.php
+++ b/core/modules/user/tests/src/Functional/UserCancelTest.php
@@ -10,6 +10,7 @@
 use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\node\Entity\Node;
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\NodeAccessTrait;
 use Drupal\Tests\BrowserTestBase;
 use Drupal\user\Entity\User;
 
@@ -21,6 +22,7 @@
 class UserCancelTest extends BrowserTestBase {
 
   use CommentTestTrait;
+  use NodeAccessTrait;
 
   /**
    * {@inheritdoc}
@@ -279,7 +281,7 @@ public function testUserBlockUnpublishNodeAccess(): void {
 
     // Setup node access
     node_access_rebuild();
-    node_access_test_add_field(NodeType::load('page'));
+    $this->addPrivateField(NodeType::load('page'));
     \Drupal::state()->set('node_access_test.private', TRUE);
 
     $this->config('user.settings')->set('cancel_method', 'user_cancel_block_unpublish')->save();