Description
- Laravel Version: 8.54.0
- PHP Version: 7.4
- Database Driver & Version: MySQL
Description:
If you run a PHPUnit test, where you call Artisan::call("route:list") and Sanctum:actingAs() aiming to obtain a response (getJson, postJson), you get into troubles because of the following:
- RouteListCommand performs $this->router->flushMiddlewareGroups(). But this affects $this->app->router within Tests\TestCase as well
TestCase BEFORE Artisan:call("route:list")
$this->app->router->getMiddlewareGroups()
array:2 [
"web" => array:6 [
0 => "App\Http\Middleware\EncryptCookies"
1 => "Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse"
2 => "Illuminate\Session\Middleware\StartSession"
3 => "Illuminate\View\Middleware\ShareErrorsFromSession"
4 => "App\Http\Middleware\VerifyCsrfToken"
5 => "Illuminate\Routing\Middleware\SubstituteBindings"
]
"api" => array:3 [
0 => "throttle:api"
1 => "Illuminate\Routing\Middleware\SubstituteBindings"
2 => "Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful"
]
]
TestCase AFTER Artisan:call("route:list")
$this->app->router->getMiddlewareGroups()
[]
Steps To Reproduce:
class WhateverTest extends TestCase {
public function testWhatever()
{
Sanctum::actingAs(User::find(1));
dump($this->app->router->getMiddlewareGroups());
Artisan::call('route:list', ["--sort" => "name", "--json" => true]);
dump($this->app->router->getMiddlewareGroups());
$response = $this->getJson("/");
$response->assertOk();
}
}
"Target class [api] does not exist."
"""
#0 /var/www/localhost/htdocs/vendor/laravel/framework/src/Illuminate/Container/Container.php(754): Illuminate\Container\Container->build()\n
#1 /var/www/localhost/htdocs/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(841): Illuminate\Container\Container->resolve()\n
#2 /var/www/localhost/htdocs/vendor/laravel/framework/src/Illuminate/Container/Container.php(692): Illuminate\Foundation\Application->resolve()\n
#3 /var/www/localhost/htdocs/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(826): Illuminate\Container\Container->make()\n
#4 /var/www/localhost/htdocs/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(205): Illuminate\Foundation\Application->make()\n
#5 /var/www/localhost/htdocs/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(179): Illuminate\Foundation\Http\Kernel->terminateMiddleware()\n
#6 /var/www/localhost/htdocs/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(513): Illuminate\Foundation\Http\Kernel->terminate()\n
#7 /var/www/localhost/htdocs/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(476): Illuminate\Foundation\Testing\TestCase->call()\n
#8 /var/www/localhost/htdocs/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php(364): Illuminate\Foundation\Testing\TestCase->json()\n
#9 /var/www/localhost/htdocs/tests/WhateverTest.php(5): Illuminate\Foundation\Testing\TestCase->getJson()\n
...
...
(main)
#5 /var/www/localhost/htdocs/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(179): Illuminate\Foundation\Http\Kernel->terminateMiddleware()\n
"Target class [api] does not exist." comes from Sanctum middlewares:
api
App\Http\Middleware\Authenticate:sanctum
which happens here:
Illuminate\Foundation\Http\Kernel.php
protected function terminateMiddleware($request, $response)
{
$middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge(
$this->gatherRouteMiddleware($request), //outputs: api App\Http\Middleware\Authenticate:sanctum
$this->middleware
);
stack #0 is just because "api" (as middleware loaded) gets into:
$instance = $this->app->make($name);