I tested dispatching closure within a test and it works as expected:
// web.php
Route::post('/test', [TestController::class, 'handle'])
->withoutMiddleware(ValidateCsrfToken::class);
// TestController.php
public function handle(Request $request)
{
Log::info('test controller start');
$data = $request->input();
dispatch(function () {
Log::info('dispatched closure executed');
});
Log::info('test controller end');
return response()->json(['status' => 'ok', 'data' => $data], 200);
}
// TestTest.php
class TestTest extends TestCase
{
public function test_example(): void
{
$response = $this->postJson('/test', ['my_data' => 'some_test_data']);
$response->assertStatus(200);
$response->assertJson([
'status' => 'ok',
'data' => [
'my_data' => 'some_test_data'
]
]);
}
}
Launching the test, it successfully passes and I see proper records in log, the closure is actually executed:
C:\project>php artisan test --filter TestTest
PASS Tests\Feature\TestTest
✓ example 0.63s
Tests: 1 passed (2 assertions)
Duration: 0.78s
// laravel.log
[2025-07-25 10:25:23] testing.INFO: test controller start
[2025-07-25 10:25:24] testing.INFO: dispatched closure executed
[2025-07-25 10:25:24] testing.INFO: test controller end
My phpunit.xml is default, having <env name="QUEUE_CONNECTION" value="sync"/>.
So, I think there is something else in your code which prevents closure dispatching...
I tested on Laravel 12.19 / PHP 8.3.10