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

Scoop7's avatar
Level 13

How do you test a middleware in 5.5 ?

Hello, How could I test my middleware ? Here I am testing if a admin can access a middleware protected route, that returns a 500, if the user does not have a privileged ip - then the middleware returns a 401 (not authorized) when trying to access the /500 page .

My test:

use App\Http\Middleware\OnlyAdminIp;
use Illuminate\Http\Request;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class HttpTests extends TestCase
{
    use DatabaseTransactions;

   /** @test */
    public function if_a_500_page_returns_a_500_response_for_admin()
    {
        $request = Request::create(config('app.url') . '500', 'GET');
        $middleware = new OnlyAdminIp();
        $response = $middleware->handle($request, function () {});
        $this->assertEquals($response->getStatusCode(), 401);
    }
}

My middleware:

namespace App\Http\Middleware;

use App\IpList;
use Closure;

class OnlyAdminIp
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $client_ip = $_SERVER["HTTP_CF_CONNECTING_IP"] ?? $request->ip(); // CDN(Cloudflare) provides the real client ip, a safeguard is used to prevent critical error if CDN is removed/changed.
        $ipList = IpList::all()
            ->pluck('ip')
            ->toArray();
        if (!in_array($client_ip, $ipList)) {
            abort(401);
        }

        return $next($request);
    }
}

And just for more clarity - the 500 route .

Route::group(['middleware' => 'admin.ip'], function () {


    Route::get('500', function () {
        abort(500);
    }); 

});

With this setup I am getting Call to a member function getStatusCode() on null Thanks in advance !

0 likes
2 replies
lostdreamer_nl's avatar

$response = $middleware->handle($request, function () {});

You're giving the middleware an empty closure as the $next method. Since it doesnt return anything, the reponse of your tested middleware (return $next($request); ) will also return NULL;

For testing middleware, you can either test the route itself and check the response, or you can test the middleware class itself (without testing to see if the middleware is actually used on a route)

You're now going for the second way.

If you want to only unit test this middleware, you could do something like this:

        $request = Request::create(config('app.url') . '500', 'GET');
        $middleware = new OnlyAdminIp();
        $response = $middleware->handle($request, function () { return true; });
        $this->assertEquals($response, true);

If the middleware does not abort, it will return the output of the $next function you're passing.

So by passing it a function that simply returns true, we can check if the middleware aborted or not.

If you also want to check if the middleware is in use on a route, you should simply do a get() request to the actual route and check for exceptions being thrown.

    try {
                $response = $this->get(config('app.url') . '500');
            } catch (HttpException $e) {
                $this->assertEquals($e->getStatusCode(), 500);
            }

1 like
Scoop7's avatar
Level 13

Came up with a solution:

    $request = Request::create(config('app.url') . '500', 'GET',[],[],[],['REMOTE_ADDR'=>'127.0.0.2']);
        $middleware = new OnlyAdminIp();
        $expectedStatusCode = 401;
        try {
          $middleware->handle($request, function () {});
        }catch(\Symfony\Component\HttpKernel\Exception\HttpException $e){
            $this->assertEquals(
                $expectedStatusCode,
                $e->getStatusCode(),
                sprintf("Expected an HTTP status of %d but got %d.", $expectedStatusCode, $e->getStatusCode())
            );
        }

Please or to participate in this conversation.