-
Notifications
You must be signed in to change notification settings - Fork 11.6k
Description
Laravel Version
11.x
PHP Version
any
Database Driver & Version
irrelevant
Description
This is similar to #53692 but a separate issue.
It seems creating a DB connection too early (in a service provider, in a specific way) and using it later causes some weird "desynchronization" when using parallel tests.
I haven't had the time to do a deep dive yet, but the issue is likely related to some reconnecting logic similar to the linked issue.
The reproduction steps may seem very specific, i.e. why am I instantiating a cache store in a service provider. In practice this happens if you just use RateLimiter::for('foo', static fn () => null)
, but that under the hood creates the cache store which seems to be the underlying cause. So the reproduction steps are as low level as I managed to trace this issue.
In a real app, e.g. one based on Fortify which rate limits logins, any call to cache()
while using the database
cache driver, will cause weird behavior. There is a test in Jetstream that directly reproduces this (it makes a request to the login route) but the side effects don't have a perceptible effect. If there were some more DB-related assertions after the request, especially comparing DB state before the request and after, you'd see it.
Steps To Reproduce
laravel new
, no starter kit, select Pest for instance- Make the following changes in
phpunit.xml
:<env name="CACHE_STORE" value="database"/> <env name="DB_CONNECTION" value="sqlite"/> <env name="DB_DATABASE" value="database/tests.sqlite"/>
touch database/tests.sqlite
- Force cache store creation in a service provider:
// AppServiceProvider::boot() cache()->getStore();
- Add a test:
test('foobar', function () { expect(DB::select('select * from users'))->toHaveCount(0); User::create(['name' => 'John Doe', 'email' => '[email protected]', 'password' => 'foobar']); expect(DB::select('select * from users'))->toHaveCount(1); cache()->put('foo', 'bar'); expect(cache('foo'))->toBe('bar'); // users table is empty! expect(DB::select('select * from users'))->toHaveCount(1); });
artisan test -p
should fail on the last assertion- If you remove the service provider call, the test passes