Fixtures and mocking
Prepare Symfony application state, distinguish browser routing from server-side mocks, and keep tests deterministic.
Prepare state through Symfony, then use the browser for the behavior the user performs. This keeps setup fast without turning a browser test into a service test.
Create data before navigation
The kernel is already booted when the test method runs, so the test container is available:
Retrieve the project's existing factory or fixture service through static::getContainer(), create the account, then authenticate and navigate. Reset persistent state between tests using the same strategy as the rest of the Symfony test suite.
PlaywrightTestCase includes a loadFixtures() extension point, but it is intentionally empty. Override it only if a shared base class gives that hook a clear project-specific contract.
Mock the layer that makes the call
Playwright routing only sees requests made by the browser. It is appropriate for browser-side fetch() calls, scripts, images, and other page resources:
$this->page->route('**/api/recommendations', static function ($route): void {
$route->fulfill([
'status' => 200,
'contentType' => 'application/json',
'body' => json_encode(['items' => []], JSON_THROW_ON_ERROR),
]);
});
$page = $this->visit('/products');
expect($page->getByText('No recommendations yet'))->toBeVisible();
If a Symfony controller calls an external service from PHP, replace that service in the test container or configure a fixture transport. The browser route cannot observe server-side HTTP traffic.
Keep failure causes visible
Prefer a small number of explicit substitutes. A suite that replaces every dependency may pass while the real application wiring is broken. Keep genuine integration where it protects the behavior under test, and mock only the dependency that makes the scenario slow, unavailable, or difficult to reproduce.
Use Network routing for browser-side interception patterns and Symfony profiler and debugging when the kernel response is unexpected.