3

I have Laravel 5.5 where I decided to group routes in files to organise them in a more meaningful way.

Here's a simplified example - the web route files live in:

app/Http/Routes/Web/static.php
app/Http/Routes/Web/test.php

static.php contains:

<?php
declare(strict_types=1);

namespace Foo\Http\Routes\Web;

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

test.php contains:

<?php
declare(strict_types=1);

namespace Foo\Http\Routes\Web;

use Illuminate\Support\Facades\Route;

Route::get('/test', function () {
    return 'test'; // just to simplify
});

RouteServiceProvider.php contains:

<?php
declare(strict_types=1);

namespace Foo\App\Providers;

use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;

class RouteServiceProvider extends ServiceProvider
{
    protected $namespace = 'Foo\Http\Controllers';

    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @return void
     */
    public function boot()
    {
        //

        parent::boot();
    }

    /**
     * Define the routes for the application.
     *
     * @return void
     */
    public function map()
    {
        $this->mapWebRoutes();
    }

    protected function mapWebRoutes()
    {
        Route::group([
            'middleware' => 'web',
            'namespace' => $this->namespace,
        ], function($router) {
            require app_path('Http/Routes/Web/static.php');
            require app_path('Http/Routes/Web/test.php');
            // more files will land here in the future
        });
    }
}

Up to now I can confirm that everything works by calling php artisan route:list:

enter image description here

Now I was going to write some tests but I require code coverage, so I added:

<logging>
    <log type="coverage-html" target="./report" charset="UTF-8"
         yui="true" highlight="true"
         lowUpperBound="50" highLowerBound="80"/>
</logging>

into my phpunit.xml.

When I call phpunit I get:

PHPUnit 7.0.1 by Sebastian Bergmann and contributors.

PHP Fatal error:  Uncaught RuntimeException: A facade root has not been set. in /Users/slick/Code/foo/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:218
Stack trace:
#0 /Users/slick/Code/foo/app/Http/Routes/Web/static.php(10): Illuminate\Support\Facades\Facade::__callStatic('get', Array)
#1 phar:///usr/local/Cellar/phpunit/7.0.1/libexec/phpunit-7.0.1.phar/php-code-coverage/CodeCoverage.php(929): include_once('/Users/slick/Co...')
#2 phar:///usr/local/Cellar/phpunit/7.0.1/libexec/phpunit-7.0.1.phar/php-code-coverage/CodeCoverage.php(243): SebastianBergmann\CodeCoverage\CodeCoverage->initializeData()
#3 phar:///usr/local/Cellar/phpunit/7.0.1/libexec/phpunit-7.0.1.phar/phpunit/Framework/TestResult.php(671): SebastianBergmann\CodeCoverage\CodeCoverage->start(Object(Tests\Feature\ExampleTest))
#4 phar:///usr/local/Cellar/phpunit/7.0.1/libexec/phpunit-7.0.1.phar/phpunit/Framework/TestCase.php(687): PHPUnit\Framework\TestResult->run(Object(Tests\Feature\ExampleTest))
#5 phar:///usr/local/Cell in /Users/slick/Code/foo/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php on line 218

Fatal error: Uncaught RuntimeException: A facade root has not been set. in /Users/slick/Code/foo/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php on line 218

enter image description here

Straight after I remove the coverage lines I added to xml file and run phpunit again - it's green.

$ phpunit PHPUnit 7.0.1 by Sebastian Bergmann and contributors.

.. 2 / 2 (100%)

Time: 381 ms, Memory: 20.00MB

OK (2 tests, 2 assertions)

What's wrong? Why phpunit with code coverage doesn't like routes in multiple files (but without coverage it works perfectly fine)?

1 Answer 1

5

Someone had the same issue and fixed that by excluding routes directories from code coverage. So I added into phpunit.xml:

<filter>
    <whitelist processUncoveredFilesFromWhitelist="true">
        <directory suffix=".php">./app</directory>
        <exclude>
            <directory suffix=".php">./app/Http/Routes</directory>
        </exclude>
    </whitelist>
</filter>

And phpunit with coverage works good.

Goshh… facades are tricky.

Sign up to request clarification or add additional context in comments.

1 Comment

Just ran into this as well. It looks like the PhpUnit code coverage class includes all files to receive the coverage, meaning if they're procedural like a routes file, they accidentally get executed on the spot. And since this process spins up before the app does, the ServiceProviders wouldn't have had a chance to define things like Facades.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.