Featured image of post Fake Requests in Slim for Your HTTP Testing Needs

Fake Requests in Slim for Your HTTP Testing Needs

Building HTTP Tests from Scratch

  • When needing HTTP testing in code, Laravel has built-in functionality for this. With Slim, we have to build our own solution.
  • After searching online for examples and finding limited resources, I decided to examine Laravel’s source code for inspiration.
  • Discovered that the core idea is to mock a Request object and execute it to get response results.
  • Implemented this approach in Slim framework accordingly.

Setting Up Test Files

  • Add autoload configuration in composer.json and run composer dump-auto:
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    }
  • Create phpunit.xml at root directory:
<phpunit bootstrap="tests/bootstrap.php">
    <testsuites>
        <testsuite name="Feature">
            <directory suffix="Test.php">tests</directory>
        </testsuite>
    </testsuites>
</phpunit>
  • Create tests/bootstrap.php with content:
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

require __DIR__ . '/../vendor/autoload.php';

$app = AppFactory::create();

$app->get('/hello/{name}', function (Request $request, Response $response, array $args) {
    $name = $args['name'];
    $response->getBody()->write("Hello, $name");
    return $response;
});

$app->get('/api/v1/users', function (Request $request, Response $response) {
    $data = [['name' => 'Bob', 'age' => 40]];
    $payload = json_encode($data);

    $response->getBody()->write($payload);
    return $response
        ->withHeader('Content-Type', 'application/json');
});

// Do not run the app here
// $app->run();

function getApplication()
{
    global $app;
    return $app;
}
  • Create test file tests/HomeTest.php:
<?php
namespace Tests;

use Nyholm\Psr7\Uri;
use PHPUnit\Framework\TestCase;
use Slim\Factory\ServerRequestCreatorFactory;

class HomeTest extends TestCase
{
    public function testHello()
    {
        $name = 'Bob';

        $serverRequestCreator = ServerRequestCreatorFactory::create();
        $request = $serverRequestCreator->createServerRequestFromGlobals();

        $uri = new Uri();
        $request = $request->withUri($uri->withPath("/hello/{$name}"));

        $response = getApplication()->handle($request);
        $responseContent = (string)$response->getBody();

        $this->assertEquals("Hello, {$name}", $responseContent);
    }

    public function testJsonApi()
    {
        $serverRequestCreator = ServerRequestCreatorFactory::create();
        $request = $serverRequestCreator->createServerRequestFromGlobals();

        // Uri and Request objects are immutable - create new instances
        $uri = new Uri();
        $request = $request->withUri($uri->withPath('api/v1/users'));
        
        // For fake query parameters:
        // $request = $request->withQueryParams([]);
        
        $response = getApplication()->handle($request);
        $responseContent = (string)$response->getBody();

        $this->assertJson($responseContent);
    }
}
  • Finally, execute tests with PHPUnit:
$ phpunit
PHPUnit 7.5.17 by Sebastian Bergmann and contributors.

..                                                                  2 / 2 (100%)

Time: 45 ms, Memory: 4.00 MB

OK (2 tests, 2 assertions)