diff --git a/django/test/runner.py b/django/test/runner.py
index 89bb6cf1fc..fe30d2289b 100644
--- a/django/test/runner.py
+++ b/django/test/runner.py
@@ -492,6 +492,7 @@ class ParallelTestSuite(unittest.TestSuite):
         Even with tblib, errors may still occur for dynamically created
         exception classes which cannot be unpickled.
         """
+        self.initialize_suite()
         counter = multiprocessing.Value(ctypes.c_int, 0)
         pool = multiprocessing.Pool(
             processes=self.processes,
@@ -962,8 +963,6 @@ class DiscoverRunner:
     def run_suite(self, suite, **kwargs):
         kwargs = self.get_test_runner_kwargs()
         runner = self.test_runner(**kwargs)
-        if hasattr(suite, "initialize_suite"):
-            suite.initialize_suite()
         try:
             return runner.run(suite)
         finally:
diff --git a/tests/test_runner/tests.py b/tests/test_runner/tests.py
index c50c54f25c..c022a6fb86 100644
--- a/tests/test_runner/tests.py
+++ b/tests/test_runner/tests.py
@@ -639,6 +639,51 @@ class CustomTestRunnerOptionsCmdlineTests(AdminScriptTestCase):
         self.assertNoOutput(out)
 
 
+class NoInitializeSuiteTestRunnerTests(SimpleTestCase):
+    @mock.patch.object(multiprocessing, "get_start_method", return_value="spawn")
+    @mock.patch(
+        "django.test.runner.ParallelTestSuite.initialize_suite",
+        side_effect=Exception("initialize_suite() is called."),
+    )
+    def test_no_initialize_suite_test_runner(self, *mocked_objects):
+        """
+        The test suite's initialize_suite() method must always be called when
+        using spawn. It cannot rely on a test runner implementation.
+        """
+
+        class NoInitializeSuiteTestRunner(DiscoverRunner):
+            def setup_test_environment(self, **kwargs):
+                return
+
+            def setup_databases(self, **kwargs):
+                return
+
+            def run_checks(self, databases):
+                return
+
+            def teardown_databases(self, old_config, **kwargs):
+                return
+
+            def teardown_test_environment(self, **kwargs):
+                return
+
+            def run_suite(self, suite, **kwargs):
+                kwargs = self.get_test_runner_kwargs()
+                runner = self.test_runner(**kwargs)
+                return runner.run(suite)
+
+        with self.assertRaisesMessage(Exception, "initialize_suite() is called."):
+            runner = NoInitializeSuiteTestRunner(
+                verbosity=0, interactive=False, parallel=2
+            )
+            runner.run_tests(
+                [
+                    "test_runner_apps.sample.tests_sample.TestDjangoTestCase",
+                    "test_runner_apps.simple.tests",
+                ]
+            )
+
+
 class Ticket17477RegressionTests(AdminScriptTestCase):
     def setUp(self):
         super().setUp()