diff --git a/CHANGELOG.md b/CHANGELOG.md
index 374c31889..ca58a4032 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,11 @@
 CHANGELOG
 =========
 
+7.4
+---
+
+ * Deprecate using `Request::sendHeaders()` after headers have already been sent; use a `StreamedResponse` instead
+
 7.3
 ---
 
diff --git a/HeaderUtils.php b/HeaderUtils.php
index a7079be9a..37953af4f 100644
--- a/HeaderUtils.php
+++ b/HeaderUtils.php
@@ -164,7 +164,7 @@ public static function unquote(string $s): string
      */
     public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string
     {
-        if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) {
+        if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE], true)) {
             throw new \InvalidArgumentException(\sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
         }
 
diff --git a/IpUtils.php b/IpUtils.php
index 11a43238b..f67e314ab 100644
--- a/IpUtils.php
+++ b/IpUtils.php
@@ -196,7 +196,7 @@ public static function anonymize(string $ip/* , int $v4Bytes = 1, int $v6Bytes =
             throw new \InvalidArgumentException('Cannot anonymize more than 4 bytes for IPv4 and 16 bytes for IPv6.');
         }
 
-        /**
+        /*
          * If the IP contains a % symbol, then it is a local-link address with scoping according to RFC 4007
          * In that case, we only care about the part before the % symbol, as the following functions, can only work with
          * the IP address itself. As the scope can leak information (containing interface name), we do not want to
diff --git a/Request.php b/Request.php
index dba930a24..c2fb16f62 100644
--- a/Request.php
+++ b/Request.php
@@ -1064,7 +1064,7 @@ public function isSecure(): bool
 
         $https = $this->server->get('HTTPS');
 
-        return $https && 'off' !== strtolower($https);
+        return $https && (!\is_string($https) || 'off' !== strtolower($https));
     }
 
     /**
@@ -1351,7 +1351,7 @@ public function isMethod(string $method): bool
      */
     public function isMethodSafe(): bool
     {
-        return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE']);
+        return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE'], true);
     }
 
     /**
@@ -1359,7 +1359,7 @@ public function isMethodSafe(): bool
      */
     public function isMethodIdempotent(): bool
     {
-        return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE']);
+        return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE'], true);
     }
 
     /**
@@ -1369,7 +1369,7 @@ public function isMethodIdempotent(): bool
      */
     public function isMethodCacheable(): bool
     {
-        return \in_array($this->getMethod(), ['GET', 'HEAD']);
+        return \in_array($this->getMethod(), ['GET', 'HEAD'], true);
     }
 
     /**
diff --git a/Response.php b/Response.php
index 638b5bf60..a2022976d 100644
--- a/Response.php
+++ b/Response.php
@@ -261,7 +261,7 @@ public function prepare(Request $request): static
             }
 
             // Fix Content-Type
-            $charset = $this->charset ?: 'UTF-8';
+            $charset = $this->charset ?: 'utf-8';
             if (!$headers->has('Content-Type')) {
                 $headers->set('Content-Type', 'text/html; charset='.$charset);
             } elseif (0 === stripos($headers->get('Content-Type') ?? '', 'text/') && false === stripos($headers->get('Content-Type') ?? '', 'charset')) {
@@ -317,6 +317,12 @@ public function sendHeaders(?int $statusCode = null): static
     {
         // headers have already been sent by the developer
         if (headers_sent()) {
+            if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
+                $statusCode ??= $this->statusCode;
+                trigger_deprecation('symfony/http-foundation', '7.4', 'Trying to use "%s::sendHeaders()" after headers have already been sent is deprecated and will throw a PHP warning in 8.0. Use a "StreamedResponse" instead.', static::class);
+                // header(\sprintf('HTTP/%s %s %s', $this->version, $statusCode, $this->statusText), true, $statusCode);
+            }
+
             return $this;
         }
 
@@ -539,7 +545,7 @@ public function getCharset(): ?string
      */
     public function isCacheable(): bool
     {
-        if (!\in_array($this->statusCode, [200, 203, 300, 301, 302, 404, 410])) {
+        if (!\in_array($this->statusCode, [200, 203, 300, 301, 302, 404, 410], true)) {
             return false;
         }
 
@@ -1248,7 +1254,7 @@ public function isNotFound(): bool
      */
     public function isRedirect(?string $location = null): bool
     {
-        return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308]) && (null === $location ?: $location == $this->headers->get('Location'));
+        return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308], true) && (null === $location ?: $location == $this->headers->get('Location'));
     }
 
     /**
@@ -1258,7 +1264,7 @@ public function isRedirect(?string $location = null): bool
      */
     public function isEmpty(): bool
     {
-        return \in_array($this->statusCode, [204, 304]);
+        return \in_array($this->statusCode, [204, 304], true);
     }
 
     /**
diff --git a/ResponseHeaderBag.php b/ResponseHeaderBag.php
index b2bdb500c..7df73f7fd 100644
--- a/ResponseHeaderBag.php
+++ b/ResponseHeaderBag.php
@@ -194,7 +194,7 @@ public function removeCookie(string $name, ?string $path = '/', ?string $domain
      */
     public function getCookies(string $format = self::COOKIES_FLAT): array
     {
-        if (!\in_array($format, [self::COOKIES_FLAT, self::COOKIES_ARRAY])) {
+        if (!\in_array($format, [self::COOKIES_FLAT, self::COOKIES_ARRAY], true)) {
             throw new \InvalidArgumentException(\sprintf('Format "%s" invalid (%s).', $format, implode(', ', [self::COOKIES_FLAT, self::COOKIES_ARRAY])));
         }
 
diff --git a/Tests/AcceptHeaderItemTest.php b/Tests/AcceptHeaderItemTest.php
index 7ec8c30fb..0e8e6fcae 100644
--- a/Tests/AcceptHeaderItemTest.php
+++ b/Tests/AcceptHeaderItemTest.php
@@ -11,14 +11,13 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\AcceptHeaderItem;
 
 class AcceptHeaderItemTest extends TestCase
 {
-    /**
-     * @dataProvider provideFromStringData
-     */
+    #[DataProvider('provideFromStringData')]
     public function testFromString($string, $value, array $attributes)
     {
         $item = AcceptHeaderItem::fromString($string);
@@ -48,9 +47,7 @@ public static function provideFromStringData()
         ];
     }
 
-    /**
-     * @dataProvider provideToStringData
-     */
+    #[DataProvider('provideToStringData')]
     public function testToString($value, array $attributes, $string)
     {
         $item = new AcceptHeaderItem($value, $attributes);
diff --git a/Tests/AcceptHeaderTest.php b/Tests/AcceptHeaderTest.php
index e972d714e..f38f1babf 100644
--- a/Tests/AcceptHeaderTest.php
+++ b/Tests/AcceptHeaderTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\AcceptHeader;
 use Symfony\Component\HttpFoundation\AcceptHeaderItem;
@@ -23,9 +24,7 @@ public function testFirst()
         $this->assertSame('text/html', $header->first()->getValue());
     }
 
-    /**
-     * @dataProvider provideFromStringData
-     */
+    #[DataProvider('provideFromStringData')]
     public function testFromString($string, array $items)
     {
         $header = AcceptHeader::fromString($string);
@@ -50,9 +49,7 @@ public static function provideFromStringData()
         ];
     }
 
-    /**
-     * @dataProvider provideToStringData
-     */
+    #[DataProvider('provideToStringData')]
     public function testToString(array $items, $string)
     {
         $header = new AcceptHeader($items);
@@ -69,9 +66,7 @@ public static function provideToStringData()
         ];
     }
 
-    /**
-     * @dataProvider provideFilterData
-     */
+    #[DataProvider('provideFilterData')]
     public function testFilter($string, $filter, array $values)
     {
         $header = AcceptHeader::fromString($string)->filter($filter);
@@ -85,9 +80,7 @@ public static function provideFilterData()
         ];
     }
 
-    /**
-     * @dataProvider provideSortingData
-     */
+    #[DataProvider('provideSortingData')]
     public function testSorting($string, array $values)
     {
         $header = AcceptHeader::fromString($string);
@@ -103,9 +96,7 @@ public static function provideSortingData()
         ];
     }
 
-    /**
-     * @dataProvider provideDefaultValueData
-     */
+    #[DataProvider('provideDefaultValueData')]
     public function testDefaultValue($acceptHeader, $value, $expectedQuality)
     {
         $header = AcceptHeader::fromString($acceptHeader);
diff --git a/Tests/BinaryFileResponseTest.php b/Tests/BinaryFileResponseTest.php
index 7627cd5ec..2e31de8e2 100644
--- a/Tests/BinaryFileResponseTest.php
+++ b/Tests/BinaryFileResponseTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use Symfony\Component\HttpFoundation\BinaryFileResponse;
 use Symfony\Component\HttpFoundation\File\File;
 use Symfony\Component\HttpFoundation\File\Stream;
@@ -79,9 +80,7 @@ public function testSetContentDispositionGeneratesSafeFallbackFilenameForWrongly
         $this->assertSame('attachment; filename=f__.html; filename*=utf-8\'\'f%F6%F6.html', $response->headers->get('Content-Disposition'));
     }
 
-    /**
-     * @dataProvider provideRanges
-     */
+    #[DataProvider('provideRanges')]
     public function testRequests($requestRange, $offset, $length, $responseRange)
     {
         $response = (new BinaryFileResponse(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream']))->setAutoEtag();
@@ -111,9 +110,7 @@ public function testRequests($requestRange, $offset, $length, $responseRange)
         $this->assertSame((string) $length, $response->headers->get('Content-Length'));
     }
 
-    /**
-     * @dataProvider provideRanges
-     */
+    #[DataProvider('provideRanges')]
     public function testRequestsWithoutEtag($requestRange, $offset, $length, $responseRange)
     {
         $response = new BinaryFileResponse(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream']);
@@ -173,9 +170,7 @@ public function testRangeRequestsWithoutLastModifiedDate()
         $this->assertNull($response->headers->get('Content-Range'));
     }
 
-    /**
-     * @dataProvider provideFullFileRanges
-     */
+    #[DataProvider('provideFullFileRanges')]
     public function testFullFileRequests($requestRange)
     {
         $response = (new BinaryFileResponse(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream']))->setAutoEtag();
@@ -243,9 +238,7 @@ public function testUnpreparedResponseSendsFullFile()
         $this->assertEquals(200, $response->getStatusCode());
     }
 
-    /**
-     * @dataProvider provideInvalidRanges
-     */
+    #[DataProvider('provideInvalidRanges')]
     public function testInvalidRequests($requestRange)
     {
         $response = (new BinaryFileResponse(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream']))->setAutoEtag();
@@ -270,9 +263,7 @@ public static function provideInvalidRanges()
         ];
     }
 
-    /**
-     * @dataProvider provideXSendfileFiles
-     */
+    #[DataProvider('provideXSendfileFiles')]
     public function testXSendfile($file)
     {
         $request = Request::create('/');
@@ -296,9 +287,7 @@ public static function provideXSendfileFiles()
         ];
     }
 
-    /**
-     * @dataProvider getSampleXAccelMappings
-     */
+    #[DataProvider('getSampleXAccelMappings')]
     public function testXAccelMapping($realpath, $mapping, $virtual)
     {
         $request = Request::create('/');
diff --git a/Tests/CookieTest.php b/Tests/CookieTest.php
index b55d29cc7..8ed32a160 100644
--- a/Tests/CookieTest.php
+++ b/Tests/CookieTest.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\Group;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Cookie;
 
@@ -19,9 +21,8 @@
  *
  * @author John Kary <john@johnkary.net>
  * @author Hugo Hamon <hugo.hamon@sensio.com>
- *
- * @group time-sensitive
  */
+#[Group('time-sensitive')]
 class CookieTest extends TestCase
 {
     public static function namesWithSpecialCharacters()
@@ -38,27 +39,21 @@ public static function namesWithSpecialCharacters()
         ];
     }
 
-    /**
-     * @dataProvider namesWithSpecialCharacters
-     */
+    #[DataProvider('namesWithSpecialCharacters')]
     public function testInstantiationThrowsExceptionIfRawCookieNameContainsSpecialCharacters($name)
     {
         $this->expectException(\InvalidArgumentException::class);
         Cookie::create($name, null, 0, null, null, null, false, true);
     }
 
-    /**
-     * @dataProvider namesWithSpecialCharacters
-     */
+    #[DataProvider('namesWithSpecialCharacters')]
     public function testWithRawThrowsExceptionIfCookieNameContainsSpecialCharacters($name)
     {
         $this->expectException(\InvalidArgumentException::class);
         Cookie::create($name)->withRaw();
     }
 
-    /**
-     * @dataProvider namesWithSpecialCharacters
-     */
+    #[DataProvider('namesWithSpecialCharacters')]
     public function testInstantiationSucceedNonRawCookieNameContainsSpecialCharacters($name)
     {
         $this->assertInstanceOf(Cookie::class, Cookie::create($name));
diff --git a/Tests/File/FileTest.php b/Tests/File/FileTest.php
index 65ce2308f..4a5a566e3 100644
--- a/Tests/File/FileTest.php
+++ b/Tests/File/FileTest.php
@@ -11,13 +11,13 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\File;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\RequiresPhpExtension;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
 use Symfony\Component\HttpFoundation\File\File;
 
-/**
- * @requires extension fileinfo
- */
+#[RequiresPhpExtension('fileinfo')]
 class FileTest extends TestCase
 {
     public function testGetMimeTypeUsesMimeTypeGuessers()
@@ -103,9 +103,7 @@ public static function getFilenameFixtures()
         ];
     }
 
-    /**
-     * @dataProvider getFilenameFixtures
-     */
+    #[DataProvider('getFilenameFixtures')]
     public function testMoveWithNonLatinName($filename, $sanitizedFilename)
     {
         $path = __DIR__.'/Fixtures/'.$sanitizedFilename;
diff --git a/Tests/File/UploadedFileTest.php b/Tests/File/UploadedFileTest.php
index 9c18ad183..0cf2f5fa3 100644
--- a/Tests/File/UploadedFileTest.php
+++ b/Tests/File/UploadedFileTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\File;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException;
 use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException;
@@ -168,9 +169,7 @@ public static function failedUploadedFile()
         }
     }
 
-    /**
-     * @dataProvider failedUploadedFile
-     */
+    #[DataProvider('failedUploadedFile')]
     public function testMoveFailed(UploadedFile $file)
     {
         $exceptionClass = match ($file->getError()) {
@@ -268,9 +267,7 @@ public function testIsValid()
         $this->assertTrue($file->isValid());
     }
 
-    /**
-     * @dataProvider uploadedFileErrorProvider
-     */
+    #[DataProvider('uploadedFileErrorProvider')]
     public function testIsInvalidOnUploadError($error)
     {
         $file = new UploadedFile(
diff --git a/Tests/Fixtures/response-functional/cookie_urlencode.expected b/Tests/Fixtures/response-functional/cookie_urlencode.expected
index 17a9efc66..1fbc95eef 100644
--- a/Tests/Fixtures/response-functional/cookie_urlencode.expected
+++ b/Tests/Fixtures/response-functional/cookie_urlencode.expected
@@ -4,8 +4,8 @@ Array
     [0] => Content-Type: text/plain; charset=utf-8
     [1] => Cache-Control: no-cache, private
     [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT
-    [3] => Set-Cookie: %3D%2C%3B%20%09%0D%0A%0B%0C=%3D%2C%3B%20%09%0D%0A%0B%0C; path=/
-    [4] => Set-Cookie: ?*():@&+$/%#[]=%3F%2A%28%29%3A%40%26%2B%24%2F%25%23%5B%5D; path=/
-    [5] => Set-Cookie: ?*():@&+$/%#[]=%3F%2A%28%29%3A%40%26%2B%24%2F%25%23%5B%5D; path=/
+    [3] => Set-Cookie: %%3D%%2C%%3B%%20%%09%%0D%%0A%%0B%%0C=%%3D%%2C%%3B%%20%%09%%0D%%0A%%0B%%0C; path=/
+    [4] => Set-Cookie: ?*():@&+$/%%#[]=%%3F%%2A%%28%%29%%3A%%40%%26%%2B%%24%%2F%%25%%23%%5B%%5D; path=/
+    [5] => Set-Cookie: ?*():@&+$/%%#[]=%%3F%%2A%%28%%29%%3A%%40%%26%%2B%%24%%2F%%25%%23%%5B%%5D; path=/
 )
 shutdown
diff --git a/Tests/HeaderUtilsTest.php b/Tests/HeaderUtilsTest.php
index 3279b9a53..6732c8788 100644
--- a/Tests/HeaderUtilsTest.php
+++ b/Tests/HeaderUtilsTest.php
@@ -11,14 +11,13 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\HeaderUtils;
 
 class HeaderUtilsTest extends TestCase
 {
-    /**
-     * @dataProvider provideHeaderToSplit
-     */
+    #[DataProvider('provideHeaderToSplit')]
     public function testSplit(array $expected, string $header, string $separator)
     {
         $this->assertSame($expected, HeaderUtils::split($header, $separator));
@@ -105,9 +104,7 @@ public function testMakeDispositionInvalidDisposition()
         HeaderUtils::makeDisposition('invalid', 'foo.html');
     }
 
-    /**
-     * @dataProvider provideMakeDisposition
-     */
+    #[DataProvider('provideMakeDisposition')]
     public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected)
     {
         $this->assertEquals($expected, HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback));
@@ -125,9 +122,7 @@ public static function provideMakeDisposition()
         ];
     }
 
-    /**
-     * @dataProvider provideMakeDispositionFail
-     */
+    #[DataProvider('provideMakeDispositionFail')]
     public function testMakeDispositionFail($disposition, $filename)
     {
         $this->expectException(\InvalidArgumentException::class);
@@ -146,9 +141,7 @@ public static function provideMakeDispositionFail()
         ];
     }
 
-    /**
-     * @dataProvider provideParseQuery
-     */
+    #[DataProvider('provideParseQuery')]
     public function testParseQuery(string $query, ?string $expected = null)
     {
         $this->assertSame($expected ?? $query, http_build_query(HeaderUtils::parseQuery($query), '', '&'));
diff --git a/Tests/IpUtilsTest.php b/Tests/IpUtilsTest.php
index 5ed3e7b22..b6261db65 100644
--- a/Tests/IpUtilsTest.php
+++ b/Tests/IpUtilsTest.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\RequiresPhpExtension;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\IpUtils;
 
@@ -31,9 +33,7 @@ public function testSeparateCachesPerProtocol()
         $this->assertTrue(IpUtils::checkIp6($ip, $subnet));
     }
 
-    /**
-     * @dataProvider getIpv4Data
-     */
+    #[DataProvider('getIpv4Data')]
     public function testIpv4($matches, $remoteAddr, $cidr)
     {
         $this->assertSame($matches, IpUtils::checkIp($remoteAddr, $cidr));
@@ -58,9 +58,7 @@ public static function getIpv4Data()
         ];
     }
 
-    /**
-     * @dataProvider getIpv6Data
-     */
+    #[DataProvider('getIpv6Data')]
     public function testIpv6($matches, $remoteAddr, $cidr)
     {
         if (!\defined('AF_INET6')) {
@@ -94,9 +92,7 @@ public static function getIpv6Data()
         ];
     }
 
-    /**
-     * @requires extension sockets
-     */
+    #[RequiresPhpExtension('sockets')]
     public function testAnIpv6WithOptionDisabledIpv6()
     {
         $this->expectException(\RuntimeException::class);
@@ -107,9 +103,7 @@ public function testAnIpv6WithOptionDisabledIpv6()
         IpUtils::checkIp('2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65');
     }
 
-    /**
-     * @dataProvider invalidIpAddressData
-     */
+    #[DataProvider('invalidIpAddressData')]
     public function testInvalidIpAddressesDoNotMatch($requestIp, $proxyIp)
     {
         $this->assertFalse(IpUtils::checkIp4($requestIp, $proxyIp));
@@ -124,9 +118,7 @@ public static function invalidIpAddressData()
         ];
     }
 
-    /**
-     * @dataProvider anonymizedIpData
-     */
+    #[DataProvider('anonymizedIpData')]
     public function testAnonymize($ip, $expected)
     {
         $this->assertSame($expected, IpUtils::anonymize($ip));
@@ -151,9 +143,7 @@ public static function anonymizedIpData()
         ];
     }
 
-    /**
-     * @dataProvider anonymizedIpDataWithBytes
-     */
+    #[DataProvider('anonymizedIpDataWithBytes')]
     public function testAnonymizeWithBytes($ip, $expected, $bytesForV4, $bytesForV6)
     {
         $this->assertSame($expected, IpUtils::anonymize($ip, $bytesForV4, $bytesForV6));
@@ -215,9 +205,7 @@ public function testAnonymizeV6WithTooManyBytes()
         IpUtils::anonymize('anything', 1, 17);
     }
 
-    /**
-     * @dataProvider getIp4SubnetMaskZeroData
-     */
+    #[DataProvider('getIp4SubnetMaskZeroData')]
     public function testIp4SubnetMaskZero($matches, $remoteAddr, $cidr)
     {
         $this->assertSame($matches, IpUtils::checkIp4($remoteAddr, $cidr));
@@ -232,9 +220,7 @@ public static function getIp4SubnetMaskZeroData()
         ];
     }
 
-    /**
-     * @dataProvider getIsPrivateIpData
-     */
+    #[DataProvider('getIsPrivateIpData')]
     public function testIsPrivateIp(string $ip, bool $matches)
     {
         $this->assertSame($matches, IpUtils::isPrivateIp($ip));
diff --git a/Tests/RateLimiter/AbstractRequestRateLimiterTest.php b/Tests/RateLimiter/AbstractRequestRateLimiterTest.php
index 087d7aeae..4316e40ca 100644
--- a/Tests/RateLimiter/AbstractRequestRateLimiterTest.php
+++ b/Tests/RateLimiter/AbstractRequestRateLimiterTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RateLimiter;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\RateLimiter\LimiterInterface;
@@ -18,9 +19,7 @@
 
 class AbstractRequestRateLimiterTest extends TestCase
 {
-    /**
-     * @dataProvider provideRateLimits
-     */
+    #[DataProvider('provideRateLimits')]
     public function testConsume(array $rateLimits, ?RateLimit $expected)
     {
         $rateLimiter = new MockAbstractRequestRateLimiter(array_map(function (RateLimit $rateLimit) {
diff --git a/Tests/RequestMatcher/AttributesRequestMatcherTest.php b/Tests/RequestMatcher/AttributesRequestMatcherTest.php
index dcb2d0b98..81e8c9aa8 100644
--- a/Tests/RequestMatcher/AttributesRequestMatcherTest.php
+++ b/Tests/RequestMatcher/AttributesRequestMatcherTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestMatcher\AttributesRequestMatcher;
@@ -18,9 +19,7 @@
 
 class AttributesRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider getData
-     */
+    #[DataProvider('getData')]
     public function test(string $key, string $regexp, bool $expected)
     {
         $matcher = new AttributesRequestMatcher([$key => $regexp]);
diff --git a/Tests/RequestMatcher/ExpressionRequestMatcherTest.php b/Tests/RequestMatcher/ExpressionRequestMatcherTest.php
index a0118e236..600801230 100644
--- a/Tests/RequestMatcher/ExpressionRequestMatcherTest.php
+++ b/Tests/RequestMatcher/ExpressionRequestMatcherTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
 use Symfony\Component\HttpFoundation\Request;
@@ -18,9 +19,7 @@
 
 class ExpressionRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider provideExpressions
-     */
+    #[DataProvider('provideExpressions')]
     public function testMatchesWhenParentMatchesIsTrue($expression, $expected)
     {
         $request = Request::create('/foo');
diff --git a/Tests/RequestMatcher/HeaderRequestMatcherTest.php b/Tests/RequestMatcher/HeaderRequestMatcherTest.php
index 47a5c7ee8..7d33ee8b3 100644
--- a/Tests/RequestMatcher/HeaderRequestMatcherTest.php
+++ b/Tests/RequestMatcher/HeaderRequestMatcherTest.php
@@ -11,15 +11,14 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestMatcher\HeaderRequestMatcher;
 
 class HeaderRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider getDataForArray
-     */
+    #[DataProvider('getDataForArray')]
     public function testArray(array $headers, bool $matches)
     {
         $matcher = new HeaderRequestMatcher(['x-foo', 'bar']);
@@ -32,9 +31,7 @@ public function testArray(array $headers, bool $matches)
         $this->assertSame($matches, $matcher->matches($request));
     }
 
-    /**
-     * @dataProvider getDataForArray
-     */
+    #[DataProvider('getDataForArray')]
     public function testCommaSeparatedString(array $headers, bool $matches)
     {
         $matcher = new HeaderRequestMatcher('x-foo, bar');
@@ -47,9 +44,7 @@ public function testCommaSeparatedString(array $headers, bool $matches)
         $this->assertSame($matches, $matcher->matches($request));
     }
 
-    /**
-     * @dataProvider getDataForSingleString
-     */
+    #[DataProvider('getDataForSingleString')]
     public function testSingleString(array $headers, bool $matches)
     {
         $matcher = new HeaderRequestMatcher('x-foo');
diff --git a/Tests/RequestMatcher/HostRequestMatcherTest.php b/Tests/RequestMatcher/HostRequestMatcherTest.php
index 903bde088..badf6878d 100644
--- a/Tests/RequestMatcher/HostRequestMatcherTest.php
+++ b/Tests/RequestMatcher/HostRequestMatcherTest.php
@@ -11,15 +11,14 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestMatcher\HostRequestMatcher;
 
 class HostRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider getData
-     */
+    #[DataProvider('getData')]
     public function test($pattern, $isMatch)
     {
         $matcher = new HostRequestMatcher($pattern);
diff --git a/Tests/RequestMatcher/IpsRequestMatcherTest.php b/Tests/RequestMatcher/IpsRequestMatcherTest.php
index 57014b50a..6a88c0419 100644
--- a/Tests/RequestMatcher/IpsRequestMatcherTest.php
+++ b/Tests/RequestMatcher/IpsRequestMatcherTest.php
@@ -11,15 +11,14 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestMatcher\IpsRequestMatcher;
 
 class IpsRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider getData
-     */
+    #[DataProvider('getData')]
     public function test($ips, bool $expected)
     {
         $matcher = new IpsRequestMatcher($ips);
diff --git a/Tests/RequestMatcher/IsJsonRequestMatcherTest.php b/Tests/RequestMatcher/IsJsonRequestMatcherTest.php
index a32172ed5..a86080590 100644
--- a/Tests/RequestMatcher/IsJsonRequestMatcherTest.php
+++ b/Tests/RequestMatcher/IsJsonRequestMatcherTest.php
@@ -11,15 +11,14 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestMatcher\IsJsonRequestMatcher;
 
 class IsJsonRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider getData
-     */
+    #[DataProvider('getData')]
     public function test($json, bool $isValid)
     {
         $matcher = new IsJsonRequestMatcher();
diff --git a/Tests/RequestMatcher/MethodRequestMatcherTest.php b/Tests/RequestMatcher/MethodRequestMatcherTest.php
index 19db917fe..9830a9482 100644
--- a/Tests/RequestMatcher/MethodRequestMatcherTest.php
+++ b/Tests/RequestMatcher/MethodRequestMatcherTest.php
@@ -11,15 +11,14 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestMatcher\MethodRequestMatcher;
 
 class MethodRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider getData
-     */
+    #[DataProvider('getData')]
     public function test(string $requestMethod, array|string $matcherMethod, bool $isMatch)
     {
         $matcher = new MethodRequestMatcher($matcherMethod);
diff --git a/Tests/RequestMatcher/PathRequestMatcherTest.php b/Tests/RequestMatcher/PathRequestMatcherTest.php
index 04ecdc913..4b4b4d15e 100644
--- a/Tests/RequestMatcher/PathRequestMatcherTest.php
+++ b/Tests/RequestMatcher/PathRequestMatcherTest.php
@@ -11,15 +11,14 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestMatcher\PathRequestMatcher;
 
 class PathRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider getData
-     */
+    #[DataProvider('getData')]
     public function test(string $regexp, bool $expected)
     {
         $matcher = new PathRequestMatcher($regexp);
diff --git a/Tests/RequestMatcher/PortRequestMatcherTest.php b/Tests/RequestMatcher/PortRequestMatcherTest.php
index 77b394f8a..53331466a 100644
--- a/Tests/RequestMatcher/PortRequestMatcherTest.php
+++ b/Tests/RequestMatcher/PortRequestMatcherTest.php
@@ -11,15 +11,14 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestMatcher\PortRequestMatcher;
 
 class PortRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider getData
-     */
+    #[DataProvider('getData')]
     public function test(int $port, bool $expected)
     {
         $matcher = new PortRequestMatcher($port);
diff --git a/Tests/RequestMatcher/QueryParameterRequestMatcherTest.php b/Tests/RequestMatcher/QueryParameterRequestMatcherTest.php
index 202ca649a..d18ab6e43 100644
--- a/Tests/RequestMatcher/QueryParameterRequestMatcherTest.php
+++ b/Tests/RequestMatcher/QueryParameterRequestMatcherTest.php
@@ -11,15 +11,14 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestMatcher\QueryParameterRequestMatcher;
 
 class QueryParameterRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider getDataForArray
-     */
+    #[DataProvider('getDataForArray')]
     public function testArray(string $uri, bool $matches)
     {
         $matcher = new QueryParameterRequestMatcher(['foo', 'bar']);
@@ -27,9 +26,7 @@ public function testArray(string $uri, bool $matches)
         $this->assertSame($matches, $matcher->matches($request));
     }
 
-    /**
-     * @dataProvider getDataForArray
-     */
+    #[DataProvider('getDataForArray')]
     public function testCommaSeparatedString(string $uri, bool $matches)
     {
         $matcher = new QueryParameterRequestMatcher('foo, bar');
@@ -37,9 +34,7 @@ public function testCommaSeparatedString(string $uri, bool $matches)
         $this->assertSame($matches, $matcher->matches($request));
     }
 
-    /**
-     * @dataProvider getDataForSingleString
-     */
+    #[DataProvider('getDataForSingleString')]
     public function testSingleString(string $uri, bool $matches)
     {
         $matcher = new QueryParameterRequestMatcher('foo');
diff --git a/Tests/RequestMatcher/SchemeRequestMatcherTest.php b/Tests/RequestMatcher/SchemeRequestMatcherTest.php
index 933b3d695..f3748447b 100644
--- a/Tests/RequestMatcher/SchemeRequestMatcherTest.php
+++ b/Tests/RequestMatcher/SchemeRequestMatcherTest.php
@@ -11,15 +11,14 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\RequestMatcher;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestMatcher\SchemeRequestMatcher;
 
 class SchemeRequestMatcherTest extends TestCase
 {
-    /**
-     * @dataProvider getData
-     */
+    #[DataProvider('getData')]
     public function test(string $requestScheme, array|string $matcherScheme, bool $isMatch)
     {
         $httpRequest = Request::create('');
diff --git a/Tests/RequestTest.php b/Tests/RequestTest.php
index 5cfb980a7..58fae2bfd 100644
--- a/Tests/RequestTest.php
+++ b/Tests/RequestTest.php
@@ -11,6 +11,9 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\RequiresPhpExtension;
+use PHPUnit\Framework\Attributes\TestWith;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Exception\BadRequestException;
 use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException;
@@ -301,18 +304,18 @@ public function testCreateWithRequestUri()
         $this->assertEquals('bar=f%5Co', $request->getQueryString());
     }
 
-    /**
-     * @testWith ["http://foo.com\\bar"]
-     *           ["\\\\foo.com/bar"]
-     *           ["a\rb"]
-     *           ["a\nb"]
-     *           ["a\tb"]
-     *           ["\u0000foo"]
-     *           ["foo\u0000"]
-     *           [" foo"]
-     *           ["foo "]
-     *           ["//"]
-     */
+    #[TestWith(['http://foo.com\bar'])]
+    #[TestWith(['\\\foo.com/bar'])]
+    #[TestWith(['a
+b'])]
+    #[TestWith(['a
+b'])]
+    #[TestWith(['a	b'])]
+    #[TestWith(['foo'])]
+    #[TestWith(['foo'])]
+    #[TestWith([' foo'])]
+    #[TestWith(['foo '])]
+    #[TestWith(['//'])]
     public function testCreateWithBadRequestUri(string $uri)
     {
         $this->expectException(BadRequestException::class);
@@ -321,9 +324,7 @@ public function testCreateWithBadRequestUri(string $uri)
         Request::create($uri);
     }
 
-    /**
-     * @dataProvider getRequestUriData
-     */
+    #[DataProvider('getRequestUriData')]
     public function testGetRequestUri($serverRequestUri, $expected, $message)
     {
         $request = new Request();
@@ -461,9 +462,7 @@ public function testGetPreferredFormat()
         $this->assertSame('xml', $request->getPreferredFormat());
     }
 
-    /**
-     * @dataProvider getFormatToMimeTypeMapProvider
-     */
+    #[DataProvider('getFormatToMimeTypeMapProvider')]
     public function testGetFormatFromMimeType($format, $mimeTypes)
     {
         $request = new Request();
@@ -489,18 +488,14 @@ public function testGetFormatFromMimeTypeWithParameters()
         $this->assertEquals('json', $request->getFormat('application/json ;charset=utf-8'));
     }
 
-    /**
-     * @dataProvider getFormatToMimeTypeMapProvider
-     */
+    #[DataProvider('getFormatToMimeTypeMapProvider')]
     public function testGetMimeTypeFromFormat($format, $mimeTypes)
     {
         $request = new Request();
         $this->assertEquals($mimeTypes[0], $request->getMimeType($format));
     }
 
-    /**
-     * @dataProvider getFormatToMimeTypeMapProvider
-     */
+    #[DataProvider('getFormatToMimeTypeMapProvider')]
     public function testGetMimeTypesFromFormat($format, $mimeTypes)
     {
         $this->assertEquals($mimeTypes, Request::getMimeTypes($format));
@@ -755,9 +750,7 @@ public function testGetUriForPath()
         $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'));
     }
 
-    /**
-     * @dataProvider getRelativeUriForPathData
-     */
+    #[DataProvider('getRelativeUriForPathData')]
     public function testGetRelativeUriForPath($expected, $pathinfo, $path)
     {
         $this->assertEquals($expected, Request::create($pathinfo)->getRelativeUriForPath($path));
@@ -815,9 +808,7 @@ public function testGetSchemeAndHttpHost()
         $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
     }
 
-    /**
-     * @dataProvider getQueryStringNormalizationData
-     */
+    #[DataProvider('getQueryStringNormalizationData')]
     public function testGetQueryString($query, $expectedQuery, $msg)
     {
         $request = new Request();
@@ -1013,9 +1004,7 @@ public function testGetSetMethod()
         $this->assertSame('POST', $request->getMethod(), '->getMethod() returns the request method if invalid type is defined in query');
     }
 
-    /**
-     * @dataProvider getClientIpsProvider
-     */
+    #[DataProvider('getClientIpsProvider')]
     public function testGetClientIp($expected, $remoteAddr, $httpForwardedFor, $trustedProxies)
     {
         $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies);
@@ -1023,9 +1012,7 @@ public function testGetClientIp($expected, $remoteAddr, $httpForwardedFor, $trus
         $this->assertEquals($expected[0], $request->getClientIp());
     }
 
-    /**
-     * @dataProvider getClientIpsProvider
-     */
+    #[DataProvider('getClientIpsProvider')]
     public function testGetClientIps($expected, $remoteAddr, $httpForwardedFor, $trustedProxies)
     {
         $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies);
@@ -1033,9 +1020,7 @@ public function testGetClientIps($expected, $remoteAddr, $httpForwardedFor, $tru
         $this->assertEquals($expected, $request->getClientIps());
     }
 
-    /**
-     * @dataProvider getClientIpsForwardedProvider
-     */
+    #[DataProvider('getClientIpsForwardedProvider')]
     public function testGetClientIpsForwarded($expected, $remoteAddr, $httpForwarded, $trustedProxies)
     {
         $request = $this->getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies);
@@ -1111,9 +1096,7 @@ public static function getClientIpsProvider()
         ];
     }
 
-    /**
-     * @dataProvider getClientIpsWithConflictingHeadersProvider
-     */
+    #[DataProvider('getClientIpsWithConflictingHeadersProvider')]
     public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXForwardedFor)
     {
         $this->expectException(ConflictingHeadersException::class);
@@ -1132,9 +1115,7 @@ public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXFor
         $request->getClientIps();
     }
 
-    /**
-     * @dataProvider getClientIpsWithConflictingHeadersProvider
-     */
+    #[DataProvider('getClientIpsWithConflictingHeadersProvider')]
     public function testGetClientIpsOnlyXHttpForwardedForTrusted($httpForwarded, $httpXForwardedFor)
     {
         $request = new Request();
@@ -1164,9 +1145,7 @@ public static function getClientIpsWithConflictingHeadersProvider()
         ];
     }
 
-    /**
-     * @dataProvider getClientIpsWithAgreeingHeadersProvider
-     */
+    #[DataProvider('getClientIpsWithAgreeingHeadersProvider')]
     public function testGetClientIpsWithAgreeingHeaders($httpForwarded, $httpXForwardedFor, $expectedIps)
     {
         $request = new Request();
@@ -1243,9 +1222,7 @@ public function getContentCantBeCalledTwiceWithResourcesProvider()
         ];
     }
 
-    /**
-     * @dataProvider getContentCanBeCalledTwiceWithResourcesProvider
-     */
+    #[DataProvider('getContentCanBeCalledTwiceWithResourcesProvider')]
     public function testGetContentCanBeCalledTwiceWithResources($first, $second)
     {
         $req = new Request();
@@ -1323,9 +1300,7 @@ public function testGetPayload()
         $this->assertSame([], $req->getPayload()->all());
     }
 
-    /**
-     * @dataProvider provideOverloadedMethods
-     */
+    #[DataProvider('provideOverloadedMethods')]
     public function testCreateFromGlobals($method)
     {
         $normalizedMethod = strtoupper($method);
@@ -1529,9 +1504,7 @@ public function testGetPreferredLanguage()
         $this->assertNull($request->getPreferredLanguage());
     }
 
-    /**
-     * @dataProvider providePreferredLanguage
-     */
+    #[DataProvider('providePreferredLanguage')]
     public function testPreferredLanguageWithLocales(?string $expectedLocale, ?string $acceptLanguage, array $locales)
     {
         $request = new Request();
@@ -1559,7 +1532,7 @@ public static function providePreferredLanguage(): iterable
         yield '"fr_FR" is selected as "fr" is a similar dialect (2)' => ['fr_FR', 'ja-JP,fr;q=0.5,en_US;q=0.3', ['en_US', 'fr_FR']];
         yield '"fr_FR" is selected as "fr_CA" is a similar dialect and has a greater "q" compared to "en_US" (2)' => ['fr_FR', 'ja-JP,fr_CA;q=0.7,ru-ru;q=0.3', ['en_US', 'fr_FR']];
         yield '"fr_FR" is selected as "fr_CA" is a similar dialect and has a greater "q" compared to "en"' => ['fr_FR', 'ja-JP,fr_CA;q=0.7,en;q=0.5', ['en_US', 'fr_FR']];
-        yield '"fr_FR" is selected as is is an exact match as well as "en_US", but with a greater "q" parameter' => ['fr_FR', 'en-us;q=0.5,fr-fr', ['en_US', 'fr_FR']];
+        yield '"fr_FR" is selected as it is an exact match as well as "en_US", but with a greater "q" parameter' => ['fr_FR', 'en-us;q=0.5,fr-fr', ['en_US', 'fr_FR']];
         yield '"hi_IN" is selected as "hi_Latn_IN" is a similar dialect' => ['hi_IN', 'fr-fr,hi_Latn_IN;q=0.5', ['hi_IN', 'en_US']];
         yield '"hi_Latn_IN" is selected as "hi_IN" is a similar dialect' => ['hi_Latn_IN', 'fr-fr,hi_IN;q=0.5', ['hi_Latn_IN', 'en_US']];
         yield '"en_US" is selected as "en_Latn_US+variants+extensions" is a similar dialect' => ['en_US', 'en-latn-us-fonapi-u-nu-numerical-x-private,fr;q=0.5', ['fr_FR', 'en_US']];
@@ -1578,9 +1551,7 @@ public function testIsXmlHttpRequest()
         $this->assertFalse($request->isXmlHttpRequest());
     }
 
-    /**
-     * @requires extension intl
-     */
+    #[RequiresPhpExtension('intl')]
     public function testIntlLocale()
     {
         $request = new Request();
@@ -1642,9 +1613,7 @@ public function testGetAcceptableContentTypes()
         $this->assertEquals(['application/vnd.wap.wmlscriptc', 'text/vnd.wap.wml', 'application/vnd.wap.xhtml+xml', 'application/xhtml+xml', 'text/html', 'multipart/mixed', '*/*'], $request->getAcceptableContentTypes());
     }
 
-    /**
-     * @dataProvider provideLanguages
-     */
+    #[DataProvider('provideLanguages')]
     public function testGetLanguages(array $expectedLocales, ?string $acceptLanguage)
     {
         $request = new Request();
@@ -1779,9 +1748,7 @@ public function testIsMethod()
         $this->assertFalse($request->isMethod('post'));
     }
 
-    /**
-     * @dataProvider getBaseUrlData
-     */
+    #[DataProvider('getBaseUrlData')]
     public function testGetBaseUrl($uri, $server, $expectedBaseUrl, $expectedPathInfo)
     {
         $request = Request::create($uri, 'GET', [], [], [], $server);
@@ -1906,9 +1873,7 @@ public static function getBaseUrlData()
         ];
     }
 
-    /**
-     * @dataProvider baseUriDetectionOnIisWithRewriteData
-     */
+    #[DataProvider('baseUriDetectionOnIisWithRewriteData')]
     public function testBaseUriDetectionOnIisWithRewrite(array $server, string $expectedBaseUrl, string $expectedPathInfo)
     {
         $request = new Request([], [], [], [], [], $server);
@@ -1962,9 +1927,7 @@ public static function baseUriDetectionOnIisWithRewriteData(): \Generator
         ];
     }
 
-    /**
-     * @dataProvider urlencodedStringPrefixData
-     */
+    #[DataProvider('urlencodedStringPrefixData')]
     public function testUrlencodedStringPrefix($string, $prefix, $expect)
     {
         $request = new Request();
@@ -2133,9 +2096,7 @@ public function testTrustedProxiesForwarded()
         $this->assertTrue($request->isSecure());
     }
 
-    /**
-     * @dataProvider iisRequestUriProvider
-     */
+    #[DataProvider('iisRequestUriProvider')]
     public function testIISRequestUri($headers, $server, $expectedRequestUri)
     {
         $request = new Request();
@@ -2252,9 +2213,7 @@ public function createRequest(): Request
         Request::setFactory(null);
     }
 
-    /**
-     * @dataProvider getLongHostNames
-     */
+    #[DataProvider('getLongHostNames')]
     public function testVeryLongHosts($host)
     {
         $start = microtime(true);
@@ -2265,9 +2224,7 @@ public function testVeryLongHosts($host)
         $this->assertLessThan(5, microtime(true) - $start);
     }
 
-    /**
-     * @dataProvider getHostValidities
-     */
+    #[DataProvider('getHostValidities')]
     public function testHostValidity($host, $isValid, $expectedHost = null, $expectedPort = null)
     {
         $request = Request::create('/');
@@ -2307,9 +2264,7 @@ public static function getLongHostNames()
         ];
     }
 
-    /**
-     * @dataProvider methodIdempotentProvider
-     */
+    #[DataProvider('methodIdempotentProvider')]
     public function testMethodIdempotent($method, $idempotent)
     {
         $request = new Request();
@@ -2333,9 +2288,7 @@ public static function methodIdempotentProvider()
         ];
     }
 
-    /**
-     * @dataProvider methodSafeProvider
-     */
+    #[DataProvider('methodSafeProvider')]
     public function testMethodSafe($method, $safe)
     {
         $request = new Request();
@@ -2359,9 +2312,7 @@ public static function methodSafeProvider()
         ];
     }
 
-    /**
-     * @dataProvider methodCacheableProvider
-     */
+    #[DataProvider('methodCacheableProvider')]
     public function testMethodCacheable($method, $cacheable)
     {
         $request = new Request();
@@ -2385,9 +2336,7 @@ public static function methodCacheableProvider()
         ];
     }
 
-    /**
-     * @dataProvider protocolVersionProvider
-     */
+    #[DataProvider('protocolVersionProvider')]
     public function testProtocolVersion($serverProtocol, $trustedProxy, $via, $expected)
     {
         if ($trustedProxy) {
@@ -2448,9 +2397,7 @@ public static function nonstandardRequestsData()
         ];
     }
 
-    /**
-     * @dataProvider nonstandardRequestsData
-     */
+    #[DataProvider('nonstandardRequestsData')]
     public function testNonstandardRequests($requestUri, $queryString, $expectedPathInfo, $expectedUri, $expectedBasePath = '', $expectedBaseUrl = null)
     {
         $expectedBaseUrl ??= $expectedBasePath;
@@ -2581,9 +2528,7 @@ public function testTrustedPortDoesNotDefaultToZero()
         $this->assertSame(80, $request->getPort());
     }
 
-    /**
-     * @dataProvider trustedProxiesRemoteAddr
-     */
+    #[DataProvider('trustedProxiesRemoteAddr')]
     public function testTrustedProxiesRemoteAddr($serverRemoteAddr, $trustedProxies, $result)
     {
         $_SERVER['REMOTE_ADDR'] = $serverRemoteAddr;
@@ -2601,10 +2546,8 @@ public static function trustedProxiesRemoteAddr()
         ];
     }
 
-    /**
-     * @testWith ["PRIVATE_SUBNETS"]
-     *           ["private_ranges"]
-     */
+    #[TestWith(['PRIVATE_SUBNETS'])]
+    #[TestWith(['private_ranges'])]
     public function testTrustedProxiesPrivateSubnets(string $key)
     {
         Request::setTrustedProxies([$key], Request::HEADER_X_FORWARDED_FOR);
@@ -2628,9 +2571,7 @@ public function testTrustedValuesCache()
         $this->assertFalse($request->isSecure());
     }
 
-    /**
-     * @dataProvider preferSafeContentData
-     */
+    #[DataProvider('preferSafeContentData')]
     public function testPreferSafeContent($server, bool $safePreferenceExpected)
     {
         $request = new Request([], [], [], [], [], $server);
diff --git a/Tests/ResponseFunctionalTest.php b/Tests/ResponseFunctionalTest.php
index e5c6c2428..3886c97f1 100644
--- a/Tests/ResponseFunctionalTest.php
+++ b/Tests/ResponseFunctionalTest.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\Group;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\Process\ExecutableFinder;
 use Symfony\Component\Process\Process;
@@ -40,9 +42,7 @@ public static function tearDownAfterClass(): void
         }
     }
 
-    /**
-     * @dataProvider provideCookie
-     */
+    #[DataProvider('provideCookie')]
     public function testCookie($fixture)
     {
         $result = file_get_contents(\sprintf('http://localhost:8054/%s.php', $fixture));
@@ -59,9 +59,7 @@ public static function provideCookie()
         }
     }
 
-    /**
-     * @group integration
-     */
+    #[Group('integration')]
     public function testInformationalResponse()
     {
         if (!(new ExecutableFinder())->find('curl')) {
diff --git a/Tests/ResponseHeaderBagTest.php b/Tests/ResponseHeaderBagTest.php
index 9e61dd684..ca21fa40f 100644
--- a/Tests/ResponseHeaderBagTest.php
+++ b/Tests/ResponseHeaderBagTest.php
@@ -11,13 +11,12 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\Group;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Cookie;
 use Symfony\Component\HttpFoundation\ResponseHeaderBag;
 
-/**
- * @group time-sensitive
- */
+#[Group('time-sensitive')]
 class ResponseHeaderBagTest extends TestCase
 {
     public function testAllPreserveCase()
diff --git a/Tests/ResponseTest.php b/Tests/ResponseTest.php
index 2c761a4f8..d1e32898c 100644
--- a/Tests/ResponseTest.php
+++ b/Tests/ResponseTest.php
@@ -11,13 +11,13 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\Group;
 use Symfony\Component\HttpFoundation\Cookie;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 
-/**
- * @group time-sensitive
- */
+#[Group('time-sensitive')]
 class ResponseTest extends ResponseTestCase
 {
     public function testToString()
@@ -63,7 +63,7 @@ public function testSend()
     public function testGetCharset()
     {
         $response = new Response();
-        $charsetOrigin = 'UTF-8';
+        $charsetOrigin = 'utf-8';
         $response->setCharset($charsetOrigin);
         $charset = $response->getCharset();
         $this->assertEquals($charsetOrigin, $charset);
@@ -534,7 +534,7 @@ public function testDefaultContentType()
         $response = new Response('foo');
         $response->prepare(new Request());
 
-        $this->assertSame('text/html; charset=UTF-8', $response->headers->get('Content-Type'));
+        $this->assertSame('text/html; charset=utf-8', $response->headers->get('Content-Type'));
     }
 
     public function testContentTypeCharset()
@@ -545,7 +545,7 @@ public function testContentTypeCharset()
         // force fixContentType() to be called
         $response->prepare(new Request());
 
-        $this->assertEquals('text/css; charset=UTF-8', $response->headers->get('Content-Type'));
+        $this->assertEquals('text/css; charset=utf-8', $response->headers->get('Content-Type'));
     }
 
     public function testContentTypeIsNull()
@@ -565,7 +565,7 @@ public function testPrepareDoesNothingIfContentTypeIsSet()
 
         $response->prepare(new Request());
 
-        $this->assertEquals('text/plain; charset=UTF-8', $response->headers->get('content-type'));
+        $this->assertEquals('text/plain; charset=utf-8', $response->headers->get('content-type'));
     }
 
     public function testPrepareDoesNothingIfRequestFormatIsNotDefined()
@@ -574,7 +574,7 @@ public function testPrepareDoesNothingIfRequestFormatIsNotDefined()
 
         $response->prepare(new Request());
 
-        $this->assertEquals('text/html; charset=UTF-8', $response->headers->get('content-type'));
+        $this->assertEquals('text/html; charset=utf-8', $response->headers->get('content-type'));
     }
 
     /**
@@ -588,7 +588,7 @@ public function testPrepareDoesNotSetContentTypeBasedOnRequestAcceptHeader()
         $request->headers->set('Accept', 'application/json');
         $response->prepare($request);
 
-        $this->assertSame('text/html; charset=UTF-8', $response->headers->get('content-type'));
+        $this->assertSame('text/html; charset=utf-8', $response->headers->get('content-type'));
     }
 
     public function testPrepareSetContentType()
@@ -879,9 +879,7 @@ public function testIsInvalid()
         $this->assertFalse($response->isInvalid());
     }
 
-    /**
-     * @dataProvider getStatusCodeFixtures
-     */
+    #[DataProvider('getStatusCodeFixtures')]
     public function testSetStatusCode($code, $text, $expectedText)
     {
         $response = new Response();
@@ -897,10 +895,10 @@ public static function getStatusCodeFixtures()
     {
         return [
             ['200', null, 'OK'],
-            ['200', false, ''],
+            ['200', '', ''],
             ['200', 'foo', 'foo'],
             ['199', null, 'unknown status'],
-            ['199', false, ''],
+            ['199', '', ''],
             ['199', 'foo', 'foo'],
         ];
     }
@@ -1005,9 +1003,7 @@ public function testSetEtag()
         $this->assertNull($response->headers->get('Etag'), '->setEtag() removes Etags when call with null');
     }
 
-    /**
-     * @dataProvider validContentProvider
-     */
+    #[DataProvider('validContentProvider')]
     public function testSetContent($content)
     {
         $response = new Response();
@@ -1021,7 +1017,7 @@ public function testSettersAreChainable()
 
         $setters = [
             'setProtocolVersion' => '1.0',
-            'setCharset' => 'UTF-8',
+            'setCharset' => 'utf-8',
             'setPublic' => null,
             'setPrivate' => null,
             'setDate' => $this->createDateTimeNow(),
@@ -1128,9 +1124,7 @@ public static function ianaCodesReasonPhrasesProvider()
         return $ianaCodesReasonPhrases;
     }
 
-    /**
-     * @dataProvider ianaCodesReasonPhrasesProvider
-     */
+    #[DataProvider('ianaCodesReasonPhrasesProvider')]
     public function testReasonPhraseDefaultsAgainstIana($code, $reasonPhrase)
     {
         $this->assertEquals($reasonPhrase, Response::$statusTexts[$code]);
diff --git a/Tests/Session/Attribute/AttributeBagTest.php b/Tests/Session/Attribute/AttributeBagTest.php
index afd281f0a..d20df5da3 100644
--- a/Tests/Session/Attribute/AttributeBagTest.php
+++ b/Tests/Session/Attribute/AttributeBagTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Attribute;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
 
@@ -76,17 +77,13 @@ public function testGetSetName()
         $this->assertEquals('foo', $this->bag->getName());
     }
 
-    /**
-     * @dataProvider attributesProvider
-     */
+    #[DataProvider('attributesProvider')]
     public function testHas($key, $value, $exists)
     {
         $this->assertEquals($exists, $this->bag->has($key));
     }
 
-    /**
-     * @dataProvider attributesProvider
-     */
+    #[DataProvider('attributesProvider')]
     public function testGet($key, $value, $expected)
     {
         $this->assertEquals($value, $this->bag->get($key));
@@ -98,9 +95,7 @@ public function testGetDefaults()
         $this->assertEquals('default', $this->bag->get('user2.login', 'default'));
     }
 
-    /**
-     * @dataProvider attributesProvider
-     */
+    #[DataProvider('attributesProvider')]
     public function testSet($key, $value, $expected)
     {
         $this->bag->set($key, $value);
diff --git a/Tests/Session/SessionTest.php b/Tests/Session/SessionTest.php
index 56ef60806..d47aec14c 100644
--- a/Tests/Session/SessionTest.php
+++ b/Tests/Session/SessionTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
 use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
@@ -98,18 +99,14 @@ public function testGet()
         $this->assertEquals(1, $this->session->get('foo', 1));
     }
 
-    /**
-     * @dataProvider setProvider
-     */
+    #[DataProvider('setProvider')]
     public function testSet($key, $value)
     {
         $this->session->set($key, $value);
         $this->assertEquals($value, $this->session->get($key));
     }
 
-    /**
-     * @dataProvider setProvider
-     */
+    #[DataProvider('setProvider')]
     public function testHas($key, $value)
     {
         $this->session->set($key, $value);
@@ -125,18 +122,14 @@ public function testReplace()
         $this->assertEquals([], $this->session->all());
     }
 
-    /**
-     * @dataProvider setProvider
-     */
+    #[DataProvider('setProvider')]
     public function testAll($key, $value, $result)
     {
         $this->session->set($key, $value);
         $this->assertEquals($result, $this->session->all());
     }
 
-    /**
-     * @dataProvider setProvider
-     */
+    #[DataProvider('setProvider')]
     public function testClear($key, $value)
     {
         $this->session->set('hi', 'fabien');
@@ -154,9 +147,7 @@ public static function setProvider()
         ];
     }
 
-    /**
-     * @dataProvider setProvider
-     */
+    #[DataProvider('setProvider')]
     public function testRemove($key, $value)
     {
         $this->session->set('hi.world', 'have a nice day');
diff --git a/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php b/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php
index ba489bdea..5db372430 100644
--- a/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php
+++ b/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php
@@ -11,13 +11,13 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\Group;
 use PHPUnit\Framework\TestCase;
 use Relay\Relay;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler;
 
-/**
- * @group time-sensitive
- */
+#[Group('time-sensitive')]
 abstract class AbstractRedisSessionHandlerTestCase extends TestCase
 {
     protected const PREFIX = 'prefix_';
@@ -108,9 +108,7 @@ public function testUpdateTimestamp()
         $this->assertGreaterThan($lowTtl, $this->redisClient->ttl(self::PREFIX.'id'));
     }
 
-    /**
-     * @dataProvider getOptionFixtures
-     */
+    #[DataProvider('getOptionFixtures')]
     public function testSupportedParam(array $options, bool $supported)
     {
         try {
@@ -132,9 +130,7 @@ public static function getOptionFixtures(): array
         ];
     }
 
-    /**
-     * @dataProvider getTtlFixtures
-     */
+    #[DataProvider('getTtlFixtures')]
     public function testUseTtlOption(int $ttl)
     {
         $options = [
diff --git a/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php b/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php
index 361d3b15d..f5947b2e5 100644
--- a/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 
 class AbstractSessionHandlerTest extends TestCase
@@ -38,9 +39,7 @@ public static function tearDownAfterClass(): void
         }
     }
 
-    /**
-     * @dataProvider provideSession
-     */
+    #[DataProvider('provideSession')]
     public function testSession($fixture)
     {
         $context = ['http' => ['header' => "Cookie: sid=123abc\r\n"]];
diff --git a/Tests/Session/Storage/Handler/IdentityMarshallerTest.php b/Tests/Session/Storage/Handler/IdentityMarshallerTest.php
index 6f15f96cb..4216e9e41 100644
--- a/Tests/Session/Storage/Handler/IdentityMarshallerTest.php
+++ b/Tests/Session/Storage/Handler/IdentityMarshallerTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\IdentityMarshaller;
 
@@ -28,9 +29,7 @@ public function testMarshall()
         $this->assertSame($values, $marshaller->marshall($values, $failed));
     }
 
-    /**
-     * @dataProvider invalidMarshallDataProvider
-     */
+    #[DataProvider('invalidMarshallDataProvider')]
     public function testMarshallInvalidData($values)
     {
         $marshaller = new IdentityMarshaller();
diff --git a/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php b/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php
index 3580bbd9b..c7bbb9b4f 100644
--- a/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php
@@ -11,15 +11,15 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RequiresPhpExtension;
 use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler;
 
-/**
- * @requires extension memcached
- *
- * @group time-sensitive
- */
+#[RequiresPhpExtension('memcached')]
+#[Group('time-sensitive')]
 class MemcachedSessionHandlerTest extends TestCase
 {
     private const PREFIX = 'prefix_';
@@ -123,9 +123,7 @@ public function testGcSession()
         $this->assertIsInt($this->storage->gc(123));
     }
 
-    /**
-     * @dataProvider getOptionFixtures
-     */
+    #[DataProvider('getOptionFixtures')]
     public function testSupportedOptions($options, $supported)
     {
         try {
diff --git a/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php b/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php
index fa07bd36c..8d9605e7e 100644
--- a/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php
@@ -20,6 +20,9 @@
 use MongoDB\Driver\Exception\ConnectionException;
 use MongoDB\Driver\Manager;
 use MongoDB\Driver\Query;
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RequiresPhpExtension;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler;
 
@@ -27,12 +30,10 @@
 
 /**
  * @author Markus Bachmann <markus.bachmann@bachi.biz>
- *
- * @group integration
- * @group time-sensitive
- *
- * @requires extension mongodb
  */
+#[RequiresPhpExtension('mongodb')]
+#[Group('integration')]
+#[Group('time-sensitive')]
 class MongoDbSessionHandlerTest extends TestCase
 {
     private const DABASE_NAME = 'sf-test';
@@ -89,7 +90,7 @@ protected function tearDown(): void
         }
     }
 
-    /** @dataProvider provideInvalidOptions */
+    #[DataProvider('provideInvalidOptions')]
     public function testConstructorShouldThrowExceptionForMissingOptions(array $options)
     {
         $this->expectException(\InvalidArgumentException::class);
diff --git a/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php b/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php
index e93ed2d09..266ae9695 100644
--- a/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php
@@ -11,6 +11,9 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\PreserveGlobalState;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
 use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
@@ -19,11 +22,9 @@
  * Test class for NativeFileSessionHandler.
  *
  * @author Drak <drak@zikula.org>
- *
- * @runTestsInSeparateProcesses
- *
- * @preserveGlobalState disabled
  */
+#[PreserveGlobalState(false)]
+#[RunTestsInSeparateProcesses]
 class NativeFileSessionHandlerTest extends TestCase
 {
     public function testConstruct()
@@ -36,9 +37,7 @@ public function testConstruct()
         $this->assertEquals('TESTING', \ini_get('session.name'));
     }
 
-    /**
-     * @dataProvider savePathDataProvider
-     */
+    #[DataProvider('savePathDataProvider')]
     public function testConstructSavePath($savePath, $expectedSavePath, $path)
     {
         new NativeFileSessionHandler($savePath);
diff --git a/Tests/Session/Storage/Handler/NullSessionHandlerTest.php b/Tests/Session/Storage/Handler/NullSessionHandlerTest.php
index 27704b909..a9254f123 100644
--- a/Tests/Session/Storage/Handler/NullSessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/NullSessionHandlerTest.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
+use PHPUnit\Framework\Attributes\PreserveGlobalState;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Session;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
@@ -20,11 +22,9 @@
  * Test class for NullSessionHandler.
  *
  * @author Drak <drak@zikula.org>
- *
- * @runTestsInSeparateProcesses
- *
- * @preserveGlobalState disabled
  */
+#[PreserveGlobalState(false)]
+#[RunTestsInSeparateProcesses]
 class NullSessionHandlerTest extends TestCase
 {
     public function testSaveHandlers()
diff --git a/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php b/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php
index 0ee76ae0b..70bbf6d2e 100644
--- a/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php
@@ -12,14 +12,15 @@
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
 use Doctrine\DBAL\Schema\Schema;
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RequiresPhpExtension;
+use PHPUnit\Framework\Attributes\RunInSeparateProcess;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
 
-/**
- * @requires extension pdo_sqlite
- *
- * @group time-sensitive
- */
+#[RequiresPhpExtension('pdo_sqlite')]
+#[Group('time-sensitive')]
 class PdoSessionHandlerTest extends TestCase
 {
     private ?string $dbFile = null;
@@ -259,9 +260,7 @@ public function testSessionDestroy()
         $this->assertSame('', $data, 'Destroyed session returns empty string');
     }
 
-    /**
-     * @runInSeparateProcess
-     */
+    #[RunInSeparateProcess]
     public function testSessionGC()
     {
         $previousLifeTime = ini_set('session.gc_maxlifetime', 1000);
@@ -309,9 +308,7 @@ public function testGetConnectionConnectsIfNeeded()
         $this->assertInstanceOf(\PDO::class, $method->invoke($storage));
     }
 
-    /**
-     * @dataProvider provideUrlDsnPairs
-     */
+    #[DataProvider('provideUrlDsnPairs')]
     public function testUrlDsn($url, $expectedDsn, $expectedUser = null, $expectedPassword = null)
     {
         $storage = new PdoSessionHandler($url);
diff --git a/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php b/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php
index 492487766..08836788e 100644
--- a/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php
@@ -11,11 +11,10 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
+use PHPUnit\Framework\Attributes\Group;
 use Predis\Client;
 
-/**
- * @group integration
- */
+#[Group('integration')]
 class PredisClusterSessionHandlerTest extends AbstractRedisSessionHandlerTestCase
 {
     protected function createRedisClient(string $host): Client
diff --git a/Tests/Session/Storage/Handler/PredisSessionHandlerTest.php b/Tests/Session/Storage/Handler/PredisSessionHandlerTest.php
index 0dc194ba1..71fc03cf4 100644
--- a/Tests/Session/Storage/Handler/PredisSessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/PredisSessionHandlerTest.php
@@ -11,11 +11,10 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
+use PHPUnit\Framework\Attributes\Group;
 use Predis\Client;
 
-/**
- * @group integration
- */
+#[Group('integration')]
 class PredisSessionHandlerTest extends AbstractRedisSessionHandlerTestCase
 {
     protected function createRedisClient(string $host): Client
diff --git a/Tests/Session/Storage/Handler/RedisArraySessionHandlerTest.php b/Tests/Session/Storage/Handler/RedisArraySessionHandlerTest.php
index af6691589..503826a19 100644
--- a/Tests/Session/Storage/Handler/RedisArraySessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/RedisArraySessionHandlerTest.php
@@ -11,9 +11,9 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
-/**
- * @group integration
- */
+use PHPUnit\Framework\Attributes\Group;
+
+#[Group('integration')]
 class RedisArraySessionHandlerTest extends AbstractRedisSessionHandlerTestCase
 {
     protected function createRedisClient(string $host): \RedisArray
diff --git a/Tests/Session/Storage/Handler/RedisClusterSessionHandlerTest.php b/Tests/Session/Storage/Handler/RedisClusterSessionHandlerTest.php
index 6a30f558f..ecd2340cc 100644
--- a/Tests/Session/Storage/Handler/RedisClusterSessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/RedisClusterSessionHandlerTest.php
@@ -11,9 +11,9 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
-/**
- * @group integration
- */
+use PHPUnit\Framework\Attributes\Group;
+
+#[Group('integration')]
 class RedisClusterSessionHandlerTest extends AbstractRedisSessionHandlerTestCase
 {
     public static function setUpBeforeClass(): void
diff --git a/Tests/Session/Storage/Handler/RedisSessionHandlerTest.php b/Tests/Session/Storage/Handler/RedisSessionHandlerTest.php
index 0bb3c1620..6565e23f4 100644
--- a/Tests/Session/Storage/Handler/RedisSessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/RedisSessionHandlerTest.php
@@ -11,9 +11,9 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
-/**
- * @group integration
- */
+use PHPUnit\Framework\Attributes\Group;
+
+#[Group('integration')]
 class RedisSessionHandlerTest extends AbstractRedisSessionHandlerTestCase
 {
     protected function createRedisClient(string $host): \Redis
diff --git a/Tests/Session/Storage/Handler/RelaySessionHandlerTest.php b/Tests/Session/Storage/Handler/RelaySessionHandlerTest.php
index 76553f96d..858b70e4a 100644
--- a/Tests/Session/Storage/Handler/RelaySessionHandlerTest.php
+++ b/Tests/Session/Storage/Handler/RelaySessionHandlerTest.php
@@ -11,14 +11,13 @@
 
 namespace Session\Storage\Handler;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RequiresPhpExtension;
 use Relay\Relay;
 use Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler\AbstractRedisSessionHandlerTestCase;
 
-/**
- * @requires extension relay
- *
- * @group integration
- */
+#[RequiresPhpExtension('relay')]
+#[Group('integration')]
 class RelaySessionHandlerTest extends AbstractRedisSessionHandlerTestCase
 {
     protected function createRedisClient(string $host): Relay
diff --git a/Tests/Session/Storage/Handler/SessionHandlerFactoryTest.php b/Tests/Session/Storage/Handler/SessionHandlerFactoryTest.php
index 41699cf56..a88ef872b 100644
--- a/Tests/Session/Storage/Handler/SessionHandlerFactoryTest.php
+++ b/Tests/Session/Storage/Handler/SessionHandlerFactoryTest.php
@@ -11,6 +11,10 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\PreserveGlobalState;
+use PHPUnit\Framework\Attributes\RequiresPhpExtension;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\SessionHandlerFactory;
@@ -20,16 +24,12 @@
  * Test class for SessionHandlerFactory.
  *
  * @author Simon <simon.chrzanowski@quentic.com>
- *
- * @runTestsInSeparateProcesses
- *
- * @preserveGlobalState disabled
  */
+#[PreserveGlobalState(false)]
+#[RunTestsInSeparateProcesses]
 class SessionHandlerFactoryTest extends TestCase
 {
-    /**
-     * @dataProvider provideConnectionDSN
-     */
+    #[DataProvider('provideConnectionDSN')]
     public function testCreateFileHandler(string $connectionDSN, string $expectedPath, string $expectedHandlerType)
     {
         $handler = SessionHandlerFactory::createHandler($connectionDSN);
@@ -48,18 +48,14 @@ public static function provideConnectionDSN(): array
         ];
     }
 
-    /**
-     * @requires extension redis
-     */
+    #[RequiresPhpExtension('redis')]
     public function testCreateRedisHandlerFromConnectionObject()
     {
         $handler = SessionHandlerFactory::createHandler($this->createMock(\Redis::class));
         $this->assertInstanceOf(RedisSessionHandler::class, $handler);
     }
 
-    /**
-     * @requires extension redis
-     */
+    #[RequiresPhpExtension('redis')]
     public function testCreateRedisHandlerFromDsn()
     {
         $handler = SessionHandlerFactory::createHandler('redis://localhost?prefix=foo&ttl=3600&ignored=bar');
diff --git a/Tests/Session/Storage/MetadataBagTest.php b/Tests/Session/Storage/MetadataBagTest.php
index 3acdcfcac..b5f33c35b 100644
--- a/Tests/Session/Storage/MetadataBagTest.php
+++ b/Tests/Session/Storage/MetadataBagTest.php
@@ -11,14 +11,14 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;
 
+use PHPUnit\Framework\Attributes\Group;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
 
 /**
  * Test class for MetadataBag.
- *
- * @group time-sensitive
  */
+#[Group('time-sensitive')]
 class MetadataBagTest extends TestCase
 {
     protected MetadataBag $bag;
diff --git a/Tests/Session/Storage/NativeSessionStorageTest.php b/Tests/Session/Storage/NativeSessionStorageTest.php
index 11c489f6b..58573b0ff 100644
--- a/Tests/Session/Storage/NativeSessionStorageTest.php
+++ b/Tests/Session/Storage/NativeSessionStorageTest.php
@@ -11,8 +11,11 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\IgnoreDeprecations;
+use PHPUnit\Framework\Attributes\PreserveGlobalState;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use PHPUnit\Framework\TestCase;
-use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
 use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
 use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
@@ -26,15 +29,11 @@
  * @author Drak <drak@zikula.org>
  *
  * These tests require separate processes.
- *
- * @runTestsInSeparateProcesses
- *
- * @preserveGlobalState disabled
  */
+#[PreserveGlobalState(false)]
+#[RunTestsInSeparateProcesses]
 class NativeSessionStorageTest extends TestCase
 {
-    use ExpectUserDeprecationMessageTrait;
-
     private string $savePath;
 
     private $initialSessionSaveHandler;
@@ -218,16 +217,18 @@ public function testCacheExpireOption()
     }
 
     /**
-     * @group legacy
-     *
      * The test must only be removed when the "session.trans_sid_tags" option is removed from PHP or when the "trans_sid_tags" option is no longer supported by the native session storage.
      */
+    #[IgnoreDeprecations]
+    #[Group('legacy')]
     public function testTransSidTagsOption()
     {
-        $this->expectUserDeprecationMessage('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "trans_sid_tags" option is deprecated and will be ignored in Symfony 8.0.');
+        $unignoredErrors = [];
 
-        $previousErrorHandler = set_error_handler(function ($errno, $errstr) use (&$previousErrorHandler) {
+        $previousErrorHandler = set_error_handler(function ($errno, $errstr) use (&$previousErrorHandler, &$unignoredErrors) {
             if ('ini_set(): Usage of session.trans_sid_tags INI setting is deprecated' !== $errstr) {
+                $unignoredErrors[] = $errstr;
+
                 return $previousErrorHandler ? $previousErrorHandler(...\func_get_args()) : false;
             }
         });
@@ -240,6 +241,8 @@ public function testTransSidTagsOption()
             restore_error_handler();
         }
 
+        $this->assertCount(1, $unignoredErrors);
+        $this->assertSame('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "trans_sid_tags" option is deprecated and will be ignored in Symfony 8.0.', $unignoredErrors[0]);
         $this->assertSame('a=href', \ini_get('session.trans_sid_tags'));
     }
 
@@ -365,18 +368,19 @@ public function testSaveHandlesNullSessionGracefully()
         $this->addToAssertionCount(1);
     }
 
-    /**
-     * @group legacy
-     */
+    #[IgnoreDeprecations]
+    #[Group('legacy')]
     public function testPassingDeprecatedOptions()
     {
-        $this->expectUserDeprecationMessage('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "sid_length" option is deprecated and will be ignored in Symfony 8.0.');
-        $this->expectUserDeprecationMessage('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "sid_bits_per_character" option is deprecated and will be ignored in Symfony 8.0.');
-        $this->expectUserDeprecationMessage('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "referer_check" option is deprecated and will be ignored in Symfony 8.0.');
-        $this->expectUserDeprecationMessage('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "use_only_cookies" option is deprecated and will be ignored in Symfony 8.0.');
-        $this->expectUserDeprecationMessage('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "use_trans_sid" option is deprecated and will be ignored in Symfony 8.0.');
-        $this->expectUserDeprecationMessage('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "trans_sid_hosts" option is deprecated and will be ignored in Symfony 8.0.');
-        $this->expectUserDeprecationMessage('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "trans_sid_tags" option is deprecated and will be ignored in Symfony 8.0.');
+        $unignoredErrors = [];
+
+        $previousErrorHandler = set_error_handler(function ($errno, $errstr) use (&$previousErrorHandler, &$unignoredErrors) {
+            if (!preg_match('/^ini_set\(\):( Disabling| Usage of)? session\..+ is deprecated$/', $errstr)) {
+                $unignoredErrors[] = $errstr;
+
+                return $previousErrorHandler ? $previousErrorHandler(...\func_get_args()) : false;
+            }
+        });
 
         $this->getStorage([
             'sid_length' => 42,
@@ -387,5 +391,14 @@ public function testPassingDeprecatedOptions()
             'trans_sid_hosts' => 'foo',
             'trans_sid_tags' => 'foo',
         ]);
+
+        $this->assertCount(7, $unignoredErrors);
+        $this->assertContains('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "sid_length" option is deprecated and will be ignored in Symfony 8.0.', $unignoredErrors);
+        $this->assertContains('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "sid_bits_per_character" option is deprecated and will be ignored in Symfony 8.0.', $unignoredErrors);
+        $this->assertContains('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "referer_check" option is deprecated and will be ignored in Symfony 8.0.', $unignoredErrors);
+        $this->assertContains('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "use_only_cookies" option is deprecated and will be ignored in Symfony 8.0.', $unignoredErrors);
+        $this->assertContains('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "use_trans_sid" option is deprecated and will be ignored in Symfony 8.0.', $unignoredErrors);
+        $this->assertContains('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "trans_sid_hosts" option is deprecated and will be ignored in Symfony 8.0.', $unignoredErrors);
+        $this->assertContains('Since symfony/http-foundation 7.2: NativeSessionStorage\'s "trans_sid_tags" option is deprecated and will be ignored in Symfony 8.0.', $unignoredErrors);
     }
 }
diff --git a/Tests/Session/Storage/PhpBridgeSessionStorageTest.php b/Tests/Session/Storage/PhpBridgeSessionStorageTest.php
index 5fbc38335..2b5350e8f 100644
--- a/Tests/Session/Storage/PhpBridgeSessionStorageTest.php
+++ b/Tests/Session/Storage/PhpBridgeSessionStorageTest.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;
 
+use PHPUnit\Framework\Attributes\PreserveGlobalState;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
 use Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage;
@@ -21,11 +23,9 @@
  * @author Drak <drak@zikula.org>
  *
  * These tests require separate processes.
- *
- * @runTestsInSeparateProcesses
- *
- * @preserveGlobalState disabled
  */
+#[PreserveGlobalState(false)]
+#[RunTestsInSeparateProcesses]
 class PhpBridgeSessionStorageTest extends TestCase
 {
     private string $savePath;
diff --git a/Tests/Session/Storage/Proxy/AbstractProxyTest.php b/Tests/Session/Storage/Proxy/AbstractProxyTest.php
index 9551d52b4..c17d0d55c 100644
--- a/Tests/Session/Storage/Proxy/AbstractProxyTest.php
+++ b/Tests/Session/Storage/Proxy/AbstractProxyTest.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy;
 
+use PHPUnit\Framework\Attributes\PreserveGlobalState;
+use PHPUnit\Framework\Attributes\RunInSeparateProcess;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
 use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
@@ -46,11 +48,8 @@ public function testIsWrapper()
         $this->assertFalse($this->proxy->isWrapper());
     }
 
-    /**
-     * @runInSeparateProcess
-     *
-     * @preserveGlobalState disabled
-     */
+    #[PreserveGlobalState(false)]
+    #[RunInSeparateProcess]
     public function testIsActive()
     {
         $this->assertFalse($this->proxy->isActive());
@@ -58,11 +57,8 @@ public function testIsActive()
         $this->assertTrue($this->proxy->isActive());
     }
 
-    /**
-     * @runInSeparateProcess
-     *
-     * @preserveGlobalState disabled
-     */
+    #[PreserveGlobalState(false)]
+    #[RunInSeparateProcess]
     public function testName()
     {
         $this->assertEquals(session_name(), $this->proxy->getName());
@@ -71,11 +67,8 @@ public function testName()
         $this->assertEquals(session_name(), $this->proxy->getName());
     }
 
-    /**
-     * @runInSeparateProcess
-     *
-     * @preserveGlobalState disabled
-     */
+    #[PreserveGlobalState(false)]
+    #[RunInSeparateProcess]
     public function testNameException()
     {
         $this->expectException(\LogicException::class);
@@ -83,11 +76,8 @@ public function testNameException()
         $this->proxy->setName('foo');
     }
 
-    /**
-     * @runInSeparateProcess
-     *
-     * @preserveGlobalState disabled
-     */
+    #[PreserveGlobalState(false)]
+    #[RunInSeparateProcess]
     public function testId()
     {
         $this->assertEquals(session_id(), $this->proxy->getId());
@@ -96,11 +86,8 @@ public function testId()
         $this->assertEquals(session_id(), $this->proxy->getId());
     }
 
-    /**
-     * @runInSeparateProcess
-     *
-     * @preserveGlobalState disabled
-     */
+    #[PreserveGlobalState(false)]
+    #[RunInSeparateProcess]
     public function testIdException()
     {
         $this->expectException(\LogicException::class);
diff --git a/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php b/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php
index d9c4974ef..6784d526e 100644
--- a/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php
+++ b/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php
@@ -11,6 +11,9 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\PreserveGlobalState;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler;
@@ -21,11 +24,9 @@
  * Tests for SessionHandlerProxy class.
  *
  * @author Drak <drak@zikula.org>
- *
- * @runTestsInSeparateProcesses
- *
- * @preserveGlobalState disabled
  */
+#[PreserveGlobalState(false)]
+#[RunTestsInSeparateProcesses]
 class SessionHandlerProxyTest extends TestCase
 {
     private MockObject&\SessionHandlerInterface $mock;
@@ -152,9 +153,7 @@ public function testUpdateTimestamp()
         $this->proxy->updateTimestamp('id', 'data');
     }
 
-    /**
-     * @dataProvider provideNativeSessionStorageHandler
-     */
+    #[DataProvider('provideNativeSessionStorageHandler')]
     public function testNativeSessionStorageSaveHandlerName($handler)
     {
         $this->assertSame('files', (new NativeSessionStorage([], $handler))->getSaveHandler()->getSaveHandlerName());
diff --git a/Tests/Test/Constraint/ResponseHeaderLocationSameTest.php b/Tests/Test/Constraint/ResponseHeaderLocationSameTest.php
index d05a9f879..4ebef26f4 100644
--- a/Tests/Test/Constraint/ResponseHeaderLocationSameTest.php
+++ b/Tests/Test/Constraint/ResponseHeaderLocationSameTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests\Test\Constraint;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\ExpectationFailedException;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
@@ -19,9 +20,7 @@
 
 class ResponseHeaderLocationSameTest extends TestCase
 {
-    /**
-     * @dataProvider provideSuccessCases
-     */
+    #[DataProvider('provideSuccessCases')]
     public function testConstraintSuccess(string $requestUrl, ?string $location, string $expectedLocation)
     {
         $request = Request::create($requestUrl);
@@ -91,9 +90,7 @@ public static function provideSuccessCases(): iterable
         yield ['http://example.com/', 'http://another-example.com', 'http://another-example.com'];
     }
 
-    /**
-     * @dataProvider provideFailureCases
-     */
+    #[DataProvider('provideFailureCases')]
     public function testConstraintFailure(string $requestUrl, ?string $location, string $expectedLocation)
     {
         $request = Request::create($requestUrl);
diff --git a/Tests/UriSignerTest.php b/Tests/UriSignerTest.php
index 81b35c28e..7dc9f1d09 100644
--- a/Tests/UriSignerTest.php
+++ b/Tests/UriSignerTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\Group;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\Clock\MockClock;
 use Symfony\Component\HttpFoundation\Exception\ExpiredSignedUriException;
@@ -20,9 +21,7 @@
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\UriSigner;
 
-/**
- * @group time-sensitive
- */
+#[Group('time-sensitive')]
 class UriSignerTest extends TestCase
 {
     public function testSign()
diff --git a/Tests/UrlHelperTest.php b/Tests/UrlHelperTest.php
index 02f6c64cf..85dfb71f7 100644
--- a/Tests/UrlHelperTest.php
+++ b/Tests/UrlHelperTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\HttpFoundation\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestStack;
@@ -20,9 +21,7 @@
 
 class UrlHelperTest extends TestCase
 {
-    /**
-     * @dataProvider getGenerateAbsoluteUrlData
-     */
+    #[DataProvider('getGenerateAbsoluteUrlData')]
     public function testGenerateAbsoluteUrl($expected, $path, $pathinfo)
     {
         $stack = new RequestStack();
@@ -55,9 +54,7 @@ public static function getGenerateAbsoluteUrlData()
         ];
     }
 
-    /**
-     * @dataProvider getGenerateAbsoluteUrlRequestContextData
-     */
+    #[DataProvider('getGenerateAbsoluteUrlRequestContextData')]
     public function testGenerateAbsoluteUrlWithRequestContext($path, $baseUrl, $host, $scheme, $httpPort, $httpsPort, $expected)
     {
         if (!class_exists(RequestContext::class)) {
@@ -71,9 +68,7 @@ public function testGenerateAbsoluteUrlWithRequestContext($path, $baseUrl, $host
         $this->assertEquals($expected, $helper->getAbsoluteUrl($path));
     }
 
-    /**
-     * @dataProvider getGenerateAbsoluteUrlRequestContextData
-     */
+    #[DataProvider('getGenerateAbsoluteUrlRequestContextData')]
     public function testGenerateAbsoluteUrlWithRequestContextAwareInterface($path, $baseUrl, $host, $scheme, $httpPort, $httpsPort, $expected)
     {
         if (!class_exists(RequestContext::class)) {
@@ -103,9 +98,7 @@ public function getContext(): RequestContext
         $this->assertEquals($expected, $helper->getAbsoluteUrl($path));
     }
 
-    /**
-     * @dataProvider getGenerateAbsoluteUrlRequestContextData
-     */
+    #[DataProvider('getGenerateAbsoluteUrlRequestContextData')]
     public function testGenerateAbsoluteUrlWithoutRequestAndRequestContext($path)
     {
         if (!class_exists(RequestContext::class)) {
@@ -146,9 +139,7 @@ public function testGenerateAbsoluteUrlWithScriptFileName()
         );
     }
 
-    /**
-     * @dataProvider getGenerateRelativePathData
-     */
+    #[DataProvider('getGenerateRelativePathData')]
     public function testGenerateRelativePath($expected, $path, $pathinfo)
     {
         $stack = new RequestStack();
diff --git a/UriSigner.php b/UriSigner.php
index bb870e43c..690021b5b 100644
--- a/UriSigner.php
+++ b/UriSigner.php
@@ -121,19 +121,12 @@ public function verify(Request|string $uri): void
         $uri = self::normalize($uri);
         $status = $this->doVerify($uri);
 
-        if (self::STATUS_VALID === $status) {
-            return;
-        }
-
-        if (self::STATUS_MISSING === $status) {
-            throw new UnsignedUriException();
-        }
-
-        if (self::STATUS_INVALID === $status) {
-            throw new UnverifiedSignedUriException();
-        }
-
-        throw new ExpiredSignedUriException();
+        match ($status) {
+            self::STATUS_VALID => null,
+            self::STATUS_INVALID => throw new UnverifiedSignedUriException(),
+            self::STATUS_EXPIRED => throw new ExpiredSignedUriException(),
+            default => throw new UnsignedUriException(),
+        };
     }
 
     private function computeHash(string $uri): string
diff --git a/composer.json b/composer.json
index a86b21b7c..9fe4c1a4b 100644
--- a/composer.json
+++ b/composer.json
@@ -24,13 +24,13 @@
     "require-dev": {
         "doctrine/dbal": "^3.6|^4",
         "predis/predis": "^1.1|^2.0",
-        "symfony/cache": "^6.4.12|^7.1.5",
-        "symfony/clock": "^6.4|^7.0",
-        "symfony/dependency-injection": "^6.4|^7.0",
-        "symfony/http-kernel": "^6.4|^7.0",
-        "symfony/mime": "^6.4|^7.0",
-        "symfony/expression-language": "^6.4|^7.0",
-        "symfony/rate-limiter": "^6.4|^7.0"
+        "symfony/cache": "^6.4.12|^7.1.5|^8.0",
+        "symfony/clock": "^6.4|^7.0|^8.0",
+        "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+        "symfony/http-kernel": "^6.4|^7.0|^8.0",
+        "symfony/mime": "^6.4|^7.0|^8.0",
+        "symfony/expression-language": "^6.4|^7.0|^8.0",
+        "symfony/rate-limiter": "^6.4|^7.0|^8.0"
     },
     "conflict": {
         "doctrine/dbal": "<3.6",
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 66c8c1836..d41c4be86 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/9.3/phpunit.xsd"
+         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.3/phpunit.xsd"
          backupGlobals="false"
          colors="true"
          bootstrap="vendor/autoload.php"
+         failOnDeprecation="true"
          failOnRisky="true"
          failOnWarning="true"
 >
@@ -19,7 +20,7 @@
         </testsuite>
     </testsuites>
 
-    <coverage>
+    <source ignoreSuppressionOfDeprecations="true">
         <include>
             <directory>./</directory>
         </include>
@@ -28,5 +29,9 @@
             <directory>./Tests</directory>
             <directory>./vendor</directory>
         </exclude>
-    </coverage>
+    </source>
+
+    <extensions>
+        <bootstrap class="Symfony\Bridge\PhpUnit\SymfonyExtension" />
+    </extensions>
 </phpunit>
