How to test signed routes?

Janez Cergolj • December 7, 2020

What are signed URLs?

From Laravel's documentation: Laravel allows you to easily create "signed" URLs to named routes. These URLs have a "signature" hash appended to the query string which allows Laravel to verify that the URL has not been modified since it was created. Signed URLs are especially useful for routes that are publicly accessible yet need a layer of protection against URL manipulation.

Use case

In my open source project - laravellte, I used it for confirming user's new email. But here I present a slightly different approach.

Testing

Let's start with a straightforward unit test:

// tests/Unit/SignedMiddlewareTest.php

/** @test */
public function assert_signed_middleware_is_applied_to_the_route()
{
    $this->assertContains('signed', $this->getMiddlewareFor('signed-route'));
}

And here is the actual route.

// routes/web.php

Route::get('signed-route', [/Http/Controllers/SignedController::class, 'index'])
    ->middleware('signed')
    ->name('signed-route');

Now we can turn our attention to feature test. We have two options: 1. use withoutMiddleware and skip signed route verification 2. use signedRoute method

Let's see the first example:

// tests/Feature/SignedControllerTest.php

/** @test */
public assert_signed_route_is_called_and_action_is_performed()
{
    $response = $this->withoutMiddleware(\Illuminate\Routing\Middleware\ValidateSignature::class)
        ->get(route('signed-route', ['params' => 'data']));

    $response->assertOk();

}

And here is the second one:

// tests/Feature/SignedControllerTest.php

/** @test */
public assert_signed_route_is_called_and_action_is_performed()
{
    $url = URL::signedRoute('signed-route', ['params' => 'data']);

    $response = $this->get($url);

    $response->assertOk();
}

We can even mix both approaches in a single test class. E.g. use the second one as a more integrated approach in a first test and use the first approach from the first one onwards.

If you ask me, either approach is acceptable. And there is no real downside or upside of using one against the other. As long as you do the testing, you should be fine.