From bf966f29cf18fda31808393a89ad31a6f849f157 Mon Sep 17 00:00:00 2001 From: Ben Younes <2910651+ousamabenyounes@users.noreply.github.com> Date: Thu, 10 Sep 2026 14:17:27 +0000 Subject: [PATCH] feat(test): keep ApiTestCase BrowserKit assertions verbose for Symfony 8.2 --- src/Symfony/Bundle/Test/ApiTestCase.php | 14 ++++++++++++++ tests/Symfony/Bundle/Test/ApiTestCaseTest.php | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/Symfony/Bundle/Test/ApiTestCase.php b/src/Symfony/Bundle/Test/ApiTestCase.php index e1076128deb..ba5484a9bcd 100644 --- a/src/Symfony/Bundle/Test/ApiTestCase.php +++ b/src/Symfony/Bundle/Test/ApiTestCase.php @@ -55,6 +55,20 @@ protected function captureExceptionHandlerStack(): void $this->symfonyErrorHandlerWasRegistered = self::isSymfonyErrorHandlerRegistered(); } + /** + * Symfony >= 8.2 flips the default verbosity of BrowserKit response assertions to false, so a failing + * assertion (e.g. assertResponseStatusCodeSame()) no longer prints the response body. That default targets + * full HTML pages; API responses are compact JSON payloads whose body is exactly what you need to debug a + * failing test. Keep verbose output on by default here so upgrading Symfony does not silently degrade API + * test failures. Projects can still opt out per suite (setBrowserKitAssertionsAsVerbose(false) in setUp(), + * which runs after this hook) or per assertion (verbose: false). + */ + #[Before] + protected function keepBrowserKitAssertionsVerbose(): void + { + self::setBrowserKitAssertionsAsVerbose(true); + } + #[After] protected function restoreExceptionHandlerStack(): void { diff --git a/tests/Symfony/Bundle/Test/ApiTestCaseTest.php b/tests/Symfony/Bundle/Test/ApiTestCaseTest.php index 3756bb92998..fd86e580eaa 100644 --- a/tests/Symfony/Bundle/Test/ApiTestCaseTest.php +++ b/tests/Symfony/Bundle/Test/ApiTestCaseTest.php @@ -425,6 +425,23 @@ public function testExplicitContentTypeIsPreserved(): void $this->assertSame('application/json', $client->getKernelBrowser()->getRequest()->headers->get('Content-Type')); } + public function testBrowserKitAssertionsStayVerboseByDefault(): void + { + // The trait's static property is flattened into ApiTestCase (which directly uses the assertions trait) + // and shared with subclasses, so read it there rather than on the trait or this subclass. + $verboseMode = new \ReflectionProperty(ApiTestCase::class, 'defaultVerboseMode'); + + // Simulate the Symfony >= 8.2 default (non-verbose) or a previous test that opted out. + self::setBrowserKitAssertionsAsVerbose(false); + fwrite(\STDOUT, \sprintf("[issue-8450] before ApiTestCase before-hook: defaultVerboseMode = %s\n", var_export($verboseMode->getValue(), true))); + + // Re-run the exact before-hook ApiTestCase registers; reverting the fix removes it and this test fails. + $this->keepBrowserKitAssertionsVerbose(); + + fwrite(\STDOUT, \sprintf("[issue-8450] after ApiTestCase before-hook: defaultVerboseMode = %s\n", var_export($verboseMode->getValue(), true))); + $this->assertTrue($verboseMode->getValue(), 'ApiTestCase must keep BrowserKit assertions verbose so failing API tests still show the response body.'); + } + public function testDoNotRebootKernelOnCreateClient(): void { self::$alwaysBootKernel = false;