Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RouteListCommand causes a trouble if you use Sanctum in a PhpUnit Test #38673

Closed
mcastania opened this issue Sep 5, 2021 · 3 comments
Closed

Comments

@mcastania
Copy link

  • 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);

@mcastania
Copy link
Author

At the moment, I had to make this temporary ugly fix to let it work:

    $middlewares = $this->app->router->getMiddlewareGroups();
    Artisan::call('route:list', ["--sort" => "name", "--json" => true]);
    $this->content = Artisan::output();
    foreach ($middlewares as $group => $list) {
        $this->app->router->middlewareGroup($group, $list);
    }

@driesvints
Copy link
Member

Hey there,

Can you first please try one of the support channels below? If you can actually identify this as a bug, feel free to open up a new issue with a link to the original one and we'll gladly help you out.

Thanks!

@mcastania
Copy link
Author

Hi, I'm afraid I don't have an account among those you suggested and I don't intend to make other logins, but Github is the account we developers have a login (since many companies make private repos and developers' accounts) and where these things should be addressed.
Feel free to have a look at the issue which, in my opinion, is a legacy issue between Test, Sanctum and Command.
I'm fine with the fix I made on my own though, despite it may be silly, but I just wanted to give the Club a contribution for an eventual improvement on the matter as I cannot swear 100% it is a bug or not.
Cheers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants