Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

nicolasbuch's avatar

How do I create a route while testing?

Hi there, I'd like to create a route in testing, I tried to inject the route to the service container but it didn't work for me, any idea:

## TestCase
    
protected function setUp()
{
    parent::setUp();

    $this->app->get('router')->get('/fifi', function() {
return 'Hello World';
});
}
    

#RouteTest
public function test_route()
{
 $this->get('/fifi')->assertStatus(404);  // Returns 404
}

Any idea?

0 likes
11 replies
ftiersch's avatar

What are you actually trying to accomplish?

Check out the RouteServiceProvider, you could add an additional mapping (for example with a testing.php) and only call that method if your environment is "testing".

nicolasbuch's avatar

That's a different solution which does not work in my case.

The question here, how could I attach some routes into the service container without creating any files?

ahmadmayahi's avatar
Level 3

Short answer: you can't create routes by calling the router in that way.

Why?

Laravel loads the application routes by looking at the RouteServiceProvider or any equivalent classes, this means that all the routes MUST to be defined into a service provider.

Take a look at the config/app.php and you'll see something like this:

/*
* Application Service Providers...
*/
...
App\Providers\RouteServiceProvider::class,
...

Let's see what Laravel documentation says about the Service Providers:

Service providers are the central place of all Laravel application bootstrapping. But, what do we mean by "bootstrapped"? In general, we mean registering things, including registering service container bindings, event listeners, middleware, and even routes. Service providers are the central place to configure your application.

https://laravel.com/docs/providers

Your code does not work because it's telling Laravel to create something that should be ready when the application is bootstraped via service providers, this is a prior step.

Solution

As @ftiersch mentioned, you might create a file named `routes/testing.php` that should only be loaded in the testing environment.
protected function mapWebRoutes()
{
    if (! App::environment('testing')) {
        return ;
    }

    Route::middleware('web')->namespace($this->namespace)->group(base_path('routes/testing.php'));
}

Best, Ahmad

1 like
Sti3bas's avatar

Short answer: you can't create routes by calling the router in that way.

@ahmadmayahi really?

/** @test */
public function example_test()
{
    \Illuminate\Support\Facades\Route::get('/example-route', function () {
        abort(123);
    });

    $this->get('/example-route')
        ->assertStatus(123);
}
PHPUnit 8.3.5 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 610 ms, Memory: 20.00 MB

OK (1 test, 1 assertion)
7 likes
lakewoodtrees's avatar

@Sti3bas I know this is an old answer but perhaps you can help me out here :) I need to create a route AND assign a middleware to it in a unit test, can I do that? for some reason the route is registering but not the middleware.

Sti3bas's avatar

@lakewoodtrees are you trying to test the middleware? if so, you don't need a route, you can write a unit test for the middleware class itself.

ahmadmayahi's avatar

@sti3bas that is interesting, it might be me who misunderstood that.

Anyway, I tried to do the same in Laravel version 5.7 BUT it didn't work for me:

It worked on version 6.0 and it also workd on a newly created version 5.7.

It seems like something wrong with the project that I tried it on.

Thanks for your post.

Tofandel's avatar

@ahmadmayahi Make sure you don't have cached routes php artisan rote:clear. What's most likely is that you have a wildcard route for 404 and you are registering your new temp route after the wildcard route is already registered, this means it will match the wildcard route first

arielenter's avatar

You guys should consider doing something like this:

Route::getRoutes()->add(Route::get('\example-url'), fn() => abort(123))->name('example'));

For some reason the following on its own:

Route::get('\example-url'), fn() => abort(123))->name('example');

Will not work for the following function, which may or may not be used in your test or the code you are testing:

route('example');

Which make me a sad panda because I don't really know why ¯_(ツ)_/¯

Aridez's avatar

@arielenter This is the one thing that actually comes close to my issue. I want to test a route middleware on isolation that interacts with the route, and I want to mock a route so if I modify any within the web.php file it won't screw up my tests.

I've tried what you said and I am not managing to make it work. I made a minimal testing class that looks like this:

<?php
namespace Tests\Unit\Http\Middleware;

use Illuminate\Support\Facades\Route;
use Tests\TestCase;

class LocalizeGuestTest extends TestCase
{

    public function test_locale_route_name()
    {
        Route::getRoutes()->add(Route::get('\example-url', fn() => abort(123)))->name('example');

        dd(route('example'));

    }
}

But it will throw this error:

1) Tests\Unit\Http\Middleware\LocalizeGuestTest::test_locale_route_name
Symfony\Component\Routing\Exception\RouteNotFoundException: Route [example] not defined.

...\vendor\laravel\framework\src\Illuminate\Routing\UrlGenerator.php:517
...\vendor\laravel\framework\src\Illuminate\Foundation\helpers.php:853
...\tests\Unit\Http\Middleware\LocalizeGuestTest.php:14

Any ideas about what could be done to solve it?

Please or to participate in this conversation.