diff --git a/modules/token_or_webform/tests/src/Functional/TokenOrWebformFunctionalBrokenTest.php b/modules/token_or_webform/tests/src/Functional/TokenOrWebformFunctionalBrokenTest.php
index 7945ee2..03ea4b8 100644
--- a/modules/token_or_webform/tests/src/Functional/TokenOrWebformFunctionalBrokenTest.php
+++ b/modules/token_or_webform/tests/src/Functional/TokenOrWebformFunctionalBrokenTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\token_or_webform\Functional;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\Tests\BrowserTestBase;
 use Drupal\user\Entity\Role;
 
@@ -10,6 +12,8 @@ use Drupal\user\Entity\Role;
  *
  * @group token_or_webform
  */
+#[Group('token_or_webform')]
+#[RunTestsInSeparateProcesses]
 class TokenOrWebformFunctionalBrokenTest extends BrowserTestBase {
 
   /**
diff --git a/modules/token_or_webform/tests/src/Functional/TokenOrWebformFunctionalTest.php b/modules/token_or_webform/tests/src/Functional/TokenOrWebformFunctionalTest.php
index ce06170..c7a8e38 100644
--- a/modules/token_or_webform/tests/src/Functional/TokenOrWebformFunctionalTest.php
+++ b/modules/token_or_webform/tests/src/Functional/TokenOrWebformFunctionalTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\token_or_webform\Functional;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\Tests\BrowserTestBase;
 use Drupal\user\Entity\Role;
 
@@ -10,6 +12,8 @@ use Drupal\user\Entity\Role;
  *
  * @group token_or_webform
  */
+#[Group('token_or_webform')]
+#[RunTestsInSeparateProcesses]
 class TokenOrWebformFunctionalTest extends BrowserTestBase {
 
   /**
diff --git a/modules/token_or_webform/tests/src/Kernel/TokenOrWebformKernelBrokenTest.php b/modules/token_or_webform/tests/src/Kernel/TokenOrWebformKernelBrokenTest.php
index 3e821f0..1b990ba 100644
--- a/modules/token_or_webform/tests/src/Kernel/TokenOrWebformKernelBrokenTest.php
+++ b/modules/token_or_webform/tests/src/Kernel/TokenOrWebformKernelBrokenTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\token_or_webform\Kernel;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\KernelTests\KernelTestBase;
 
 /**
@@ -10,6 +12,8 @@ use Drupal\KernelTests\KernelTestBase;
  * @group token_or_webform
  * @requires module token
  */
+#[Group('token_or_webform')]
+#[RunTestsInSeparateProcesses]
 class TokenOrWebformKernelBrokenTest extends KernelTestBase {
 
   /**
diff --git a/modules/token_or_webform/tests/src/Kernel/TokenOrWebformKernelTest.php b/modules/token_or_webform/tests/src/Kernel/TokenOrWebformKernelTest.php
index ab30ad4..0b39a29 100644
--- a/modules/token_or_webform/tests/src/Kernel/TokenOrWebformKernelTest.php
+++ b/modules/token_or_webform/tests/src/Kernel/TokenOrWebformKernelTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\token_or_webform\Kernel;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\KernelTests\KernelTestBase;
 
 /**
@@ -10,6 +12,8 @@ use Drupal\KernelTests\KernelTestBase;
  * @group token_or_webform
  * @requires module token
  */
+#[Group('token_or_webform')]
+#[RunTestsInSeparateProcesses]
 class TokenOrWebformKernelTest extends KernelTestBase {
 
   /**
diff --git a/modules/token_or_webform/token_or_webform.info.yml b/modules/token_or_webform/token_or_webform.info.yml
index f5be24d..81a0510 100644
--- a/modules/token_or_webform/token_or_webform.info.yml
+++ b/modules/token_or_webform/token_or_webform.info.yml
@@ -1,7 +1,7 @@
 name: Token Or Webform
 type: module
 description: Support for token_or in webform.
-core_version_requirement: ^9.2 || ^10 || ^11
+core_version_requirement: ^10.1 || ^11 || ^12
 dependencies:
   - webform:webform
   - token_or:token_or
diff --git a/src/Hook/TokenOrHooks.php b/src/Hook/TokenOrHooks.php
new file mode 100644
index 0000000..bb3cbb7
--- /dev/null
+++ b/src/Hook/TokenOrHooks.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Drupal\token_or\Hook;
+
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
+/**
+ * Hook implementations for token_or.
+ */
+class TokenOrHooks {
+  use StringTranslationTrait;
+
+  /**
+   * Implements hook_help().
+   */
+  #[Hook('help')]
+  public function help($route_name, RouteMatchInterface $route_match) {
+    switch ($route_name) {
+      // Main module help for the token_or module.
+      case 'help.page.token_or':
+        $output = '';
+        $output .= '<h3>' . $this->t('About') . '</h3>';
+        $output .= '<p>' . $this->t('This module simply extends the token module to use "OR" logic within a single token. It returns the first token or string that is not empty.') . '</p>';
+        return $output;
+    }
+  }
+
+  /**
+   * Implements hook_tokens_pre_alter().
+   */
+  #[Hook('tokens_pre_alter')]
+  public static function tokensPreAlter(&$text, $data, $options) {
+    \Drupal::service('token_or.tokens_pre_alter')->tokensPreAlter($text, $data, $options);
+  }
+
+}
diff --git a/tests/modules/token_or_test/src/Hook/TokenOrTestHooks.php b/tests/modules/token_or_test/src/Hook/TokenOrTestHooks.php
new file mode 100644
index 0000000..25b2852
--- /dev/null
+++ b/tests/modules/token_or_test/src/Hook/TokenOrTestHooks.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace Drupal\token_or_test\Hook;
+
+use Drupal\Core\Render\BubbleableMetadata;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
+/**
+ * Hook implementations for token_or_test.
+ */
+class TokenOrTestHooks {
+  use StringTranslationTrait;
+
+  /**
+   * Implements hook_token_info().
+   */
+  #[Hook('token_info')]
+  public function tokenInfo() {
+    $info = [];
+    $info['tokens']['token_or']['test'] = [
+      'name' => $this->t('A test token'),
+      'description' => NULL,
+    ];
+    $info['tokens']['token_or']['test2'] = [
+      'name' => $this->t('Another test token'),
+      'description' => NULL,
+    ];
+    $info['tokens']['token_or']['empty'] = [
+      'name' => $this->t('An empty token'),
+      'description' => NULL,
+    ];
+    $info['tokens']['token_or']['empty2'] = [
+      'name' => $this->t('Another empty token'),
+      'description' => NULL,
+    ];
+    return $info;
+  }
+
+  /**
+   * Implements hook_token_info_alter().
+   */
+  #[Hook('token_info_alter')]
+  public static function tokenInfoAlter(&$info) {
+    // Add missing name properties to tokens.
+    $info['types']['date']['name'] = 'date';
+    $info['tokens']['date']['custom']['name'] = 'date-custom';
+    $info['tokens']['user']['url']['name'] = 'user-url';
+  }
+
+  /**
+   * Implements hook_tokens().
+   */
+  #[Hook('tokens')]
+  public static function tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
+    $replacements = [];
+    if ($type == 'token_or') {
+      foreach ($tokens as $name => $original) {
+        switch ($name) {
+          case 'test':
+            $replacements[$original] = 'test';
+            break;
+
+          case 'test2':
+            $replacements[$original] = 'test2';
+            break;
+
+          case 'empty':
+          case 'empty2':
+            $replacements[$original] = '';
+            break;
+        }
+      }
+    }
+    return $replacements;
+  }
+
+}
diff --git a/tests/modules/token_or_test/token_or_test.module b/tests/modules/token_or_test/token_or_test.module
index 14f746c..e19d511 100644
--- a/tests/modules/token_or_test/token_or_test.module
+++ b/tests/modules/token_or_test/token_or_test.module
@@ -5,69 +5,30 @@
  * Token or test token info.
  */
 
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\token_or_test\Hook\TokenOrTestHooks;
 use Drupal\Core\Render\BubbleableMetadata;
 
 /**
  * Implements hook_token_info().
  */
+#[LegacyHook]
 function token_or_test_token_info() {
-  $info = [];
-  $info['tokens']['token_or']['test'] = [
-    'name' => t('A test token'),
-    'description' => NULL,
-  ];
-
-  $info['tokens']['token_or']['test2'] = [
-    'name' => t('Another test token'),
-    'description' => NULL,
-  ];
-
-  $info['tokens']['token_or']['empty'] = [
-    'name' => t('An empty token'),
-    'description' => NULL,
-  ];
-  $info['tokens']['token_or']['empty2'] = [
-    'name' => t('Another empty token'),
-    'description' => NULL,
-  ];
-
-  return $info;
+  return \Drupal::service(TokenOrTestHooks::class)->tokenInfo();
 }
 
 /**
  * Implements hook_token_info_alter().
  */
+#[LegacyHook]
 function token_or_test_token_info_alter(&$info) {
-  // Add missing name properties to tokens.
-  $info['types']['date']['name'] = 'date';
-  $info['tokens']['date']['custom']['name'] = 'date-custom';
-  $info['tokens']['user']['url']['name'] = 'user-url';
+  \Drupal::service(TokenOrTestHooks::class)->tokenInfoAlter($info);
 }
 
 /**
  * Implements hook_tokens().
  */
+#[LegacyHook]
 function token_or_test_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
-  $replacements = [];
-
-  if ($type == 'token_or') {
-    foreach ($tokens as $name => $original) {
-      switch ($name) {
-        case 'test':
-          $replacements[$original] = 'test';
-          break;
-
-        case 'test2':
-          $replacements[$original] = 'test2';
-          break;
-
-        case 'empty':
-        case 'empty2':
-          $replacements[$original] = '';
-          break;
-      }
-    }
-  }
-
-  return $replacements;
+  return \Drupal::service(TokenOrTestHooks::class)->tokens($type, $tokens, $data, $options, $bubbleable_metadata);
 }
diff --git a/tests/modules/token_or_test/token_or_test.services.yml b/tests/modules/token_or_test/token_or_test.services.yml
new file mode 100644
index 0000000..f44d922
--- /dev/null
+++ b/tests/modules/token_or_test/token_or_test.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\token_or_test\Hook\TokenOrTestHooks:
+    class: Drupal\token_or_test\Hook\TokenOrTestHooks
+    autowire: true
diff --git a/tests/src/Kernel/TokenOrTest.php b/tests/src/Kernel/TokenOrTest.php
index 51b83ed..e1aa5b9 100644
--- a/tests/src/Kernel/TokenOrTest.php
+++ b/tests/src/Kernel/TokenOrTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\token_or\Kernel;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\KernelTests\KernelTestBase;
 
 /**
@@ -10,6 +12,8 @@ use Drupal\KernelTests\KernelTestBase;
  * @group token_or
  * @requires module token
  */
+#[Group('token_or')]
+#[RunTestsInSeparateProcesses]
 class TokenOrTest extends KernelTestBase {
 
   /**
diff --git a/token_or.info.yml b/token_or.info.yml
index 56bd5ac..40c36b0 100644
--- a/token_or.info.yml
+++ b/token_or.info.yml
@@ -1,6 +1,6 @@
 name: Token Or
 description: Token Or
 type: module
-core_version_requirement: ^9.2 || ^10 || ^11
+core_version_requirement: ^10.1 || ^11 || ^12
 dependencies:
   - token:token
diff --git a/token_or.module b/token_or.module
index cafb1d3..d4dd7ee 100644
--- a/token_or.module
+++ b/token_or.module
@@ -5,25 +5,22 @@
  * Use case: Open Graph image with default fallback.
  */
 
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\token_or\Hook\TokenOrHooks;
 use Drupal\Core\Routing\RouteMatchInterface;
 
 /**
  * Implements hook_help().
  */
+#[LegacyHook]
 function token_or_help($route_name, RouteMatchInterface $route_match) {
-  switch ($route_name) {
-    // Main module help for the token_or module.
-    case 'help.page.token_or':
-      $output = '';
-      $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('This module simply extends the token module to use "OR" logic within a single token. It returns the first token or string that is not empty.') . '</p>';
-      return $output;
-  }
+  return \Drupal::service(TokenOrHooks::class)->help($route_name, $route_match);
 }
 
 /**
  * Implements hook_tokens_pre_alter().
  */
+#[LegacyHook]
 function token_or_tokens_pre_alter(&$text, $data, $options) {
-  \Drupal::service('token_or.tokens_pre_alter')->tokensPreAlter($text, $data, $options);
+  \Drupal::service(TokenOrHooks::class)->tokensPreAlter($text, $data, $options);
 }
diff --git a/token_or.services.yml b/token_or.services.yml
index 9a2a6c6..afebfb8 100644
--- a/token_or.services.yml
+++ b/token_or.services.yml
@@ -2,3 +2,7 @@ services:
   token_or.tokens_pre_alter:
     class: Drupal\token_or\TokenOrTokensPreAlter
     arguments: ['@token']
+
+  Drupal\token_or\Hook\TokenOrHooks:
+    class: Drupal\token_or\Hook\TokenOrHooks
+    autowire: true
