Laravel 路由上的 PHPunit 测试总是返回 404

Posted

技术标签:

【中文标题】Laravel 路由上的 PHPunit 测试总是返回 404【英文标题】:PHPunit tests on Laravel routes always returns 404 【发布时间】:2020-11-11 10:03:36 【问题描述】:

我刚开始在我的 laravel 应用程序上编写 phpUnit 路由测试,它通过浏览器和 Postman 运行良好,但不是通过 PHPunit。

示例:在本次测试中

public function test_getAll()
    $this->withoutExceptionHandling(); // If i comment this line I get the 404 and not the error shown below

    $response = $this->get('/api/users');
    $response->assertStatus(401);

我明白了:

PHPUnit 8.5.3 by Sebastian Bergmann and contributors.

.E                                                                  2 / 2 (100%)

Time: 1.89 seconds, Memory: 8.00 MB

There was 1 error:

1) Tests\Feature\Users\UserRoute_SuperAdminTest::test_getAll
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: GET http://localhost/cms/api/users

E:\www\projects\cms-php\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithExceptionHandling.php:126
E:\www\projects\cms-php\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php:415
E:\www\projects\cms-php\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php:113
E:\www\projects\cms-php\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests.php:468
E:\www\projects\cms-php\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests.php:258
E:\www\projects\cms-php\tests\Feature\Users\UsersRoute-SuperAdmin_Test.php:45

奇怪的是:如果我将 URL 更改为:

$response = $this->get('http://anythingatallinhere/api/users');

我得到了我应该得到的 401 响应。

更多上下文信息来解决问题。

我的 env APP_URL 是 APP_URL=http://localhost/cms,我正在以这种方式动态注册路由:我有一个 CoreServiceProvider,其启动过程如下:

public function boot()
    
       [...]
        $moduleController = app()->make(ModuleController::class);
        $moduleController->registerCoreRoutes();
       [...]
    

在模块控制器上:

function registerCoreRoutes()
        foreach($this->allValidated as $moduleAlias => $registeredModule)
            $modName = ucfirst(str_replace('core/', '', strtolower($moduleAlias)));
            $namespace = 'App\Api\Core' . '\\' . $modName . '\Controllers';

            try 
                foreach ($registeredModule['routerFiles'] as $key => $routerInfo)
                    $routePath = app_path('Api/Core/' . $modName . '/Routes/' . $routerInfo['fileName'] . '.php');
                    $prefix = 'api/' . $routerInfo['path'];

                    $this->pathToModule[$routerInfo['path']] = $moduleAlias;

                    Route::prefix($prefix)
                        ->namespace($namespace)
                        ->group($routePath);
                
                $this->allRegistered[$moduleAlias] = $registeredModule;
             catch (\Throwable $th) 
                var_dump('Core module route registration failed');
                $this->allRegistered = [];
                throw $th;
            
        
    

如果我使用php artisan route:list,它们也都已正确注册。

【问题讨论】:

试试这个$response = $this->get('api/users'); 已经尝试了我想到的所有 URL 组合,包括这个。我得到了同样的东西 routes:list 中相关行的完整结果是什么?如果您从名称解析路由并在测试中使用它会发生什么,例如转储(路线('api.users')); $this->get(route('api.users')); @JamesClarkDeveloper 它太大而无法作为答案发布,所以我将发布前 2 个:| | GET|HEAD | api/users | users.list | App\Api\Core\User\Controllers\UserController@getAll | authjwt,getUserResource,can:read | | | PUT | api/users/editbasic/id | users.editBasic | App\Api\Core\User\Controllers\UserController@editBasicInfo | authjwt,getUserResource,can:update | @JamesClarkDeveloper 我做了你刚才提到的事情,但仍然返回相同的错误:dump(route('users.list')); $response = $this->get(route('users.list'));PHPUnit 8.5.3 by Sebastian Bergmann and contributors. .E 2 / 2 (100%)"http://localhost/cms/api/users" Time: 2.2 seconds, Memory: 8.00 MB There was 1 error: 1) Tests\Feature\Users\UserRoute_SuperAdminTest::test_getAll Symfony\Component\HttpKernel\Exception\NotFoundHttpException: GET http://localhost/cms/api/users 【参考方案1】:

我最近遇到了类似的问题,但是运行这些后它就可以了:

php artisan config:clear
php artisan config:cache

特别是如果您更改了 .env 文件中刚刚更改的 APP_URL。

您也可以尝试在 phpunit.xml 文件中将 processIsolation 设置为 true

<phpunit backupGlobals="false"
 backupStaticAttributes="false"
 bootstrap="bootstrap/autoload.php"
 colors="true"
 convertErrorsToExceptions="true"
 convertNoticesToExceptions="true"
 convertWarningsToExceptions="true"
 processIsolation="true"
 stopOnFailure="false">

编辑: 如果以上都不起作用,您还可以创建另一个.env.testing 并将您的APP_URL 设置为http://localhost。 PHPUnit 将使用该文件中的变量。无论您的应用程序的实际 URL 是什么,这都有效

【讨论】:

嘿,@Clement Sam。感谢您的回答。已经试过了。尝试了这些和php artisan route:clearcomposer dump-autoload 以及 我已经编辑了我的答案以包含我通常使用的替代解决方案 您也可以创建另一个.env.testing 并将您的APP_URL 设置为http://localhost。 PHPUnit 将使用该文件中的变量。无论您的应用程序的实际 URL 是什么,这都有效 我已经有了processIsolation="true",因为我正在寻找关于堆栈溢出的无数解决方案。另外我已经有一个.env.testing 文件,其中APP_URL 设置为http://localhost/cms。将其更改为 http://localhost 就可以了。现在它工作正常。由于/cms 是网址的一部分,你知道为什么它没有它就可以工作吗?

以上是关于Laravel 路由上的 PHPunit 测试总是返回 404的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Laravel 中的 PHPUnit 不能访问存在的路由?

Laravel 路由仅在 phpunit 测试期间返回 302 而不是 404 响应

Laravel - PHPUnit 中的伪造路由

使用 phpunit 进行 Laravel 测试

看不到响应获取请求 laravel phpunit

Laravel 5.4 上的示例 PHPUnit 测试失败并显示 404