Rodrigo Casanova
Rodrigo Casanova

Reputation: 59

PHPunit tests on Laravel routes always returns 404

I just began writing PHPUnit route tests on my laravel application and it's working fine via browser and Postman, not via PHPunit though.

Example: on this test

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

I get:

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

The weird thing is: if i change the URL to:

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

I get the 401 response that I should.

More context info to solve the problem.

My env APP_URL is APP_URL=http://localhost/cms and I am registering routes dynamically this way: I have a CoreServiceProvider with a boot procedure like this:

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

on ModuleController:

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;
            }
        }
    }

If I use php artisan route:list they are all there properly registered as well.

Upvotes: 2

Views: 611

Answers (2)

Fadhili Njagi
Fadhili Njagi

Reputation: 158

The easiest way would be to set APP_URL to http://localhost in the phpunit.xml file by adding this line:

<server name="APP_URL" value="http://localhost"/>

This method is best if you want to the variables in .env to still be available during testing. Creating your own .env.testing file will override all .env variables.

Upvotes: 0

Clement Sam
Clement Sam

Reputation: 750

I had a similar problem recently but it worked after running these:

php artisan config:clear
php artisan config:cache

Especially if you changed the just changed the APP_URL in your .env file.

You could also try setting processIsolation to true in your phpunit.xml file:

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

EDIT: If none of the above works, you could also create another .env.testing and set your APP_URL to http://localhost. PHPUnit will use variables from that file. This works regardless of the actual URL of your application

Upvotes: 1

Related Questions