bentools/test-http-client

Test Symfony applications with HttpClient interface without a real HTTP server

Installs: 2

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/bentools/test-http-client

1.0.0 2026-02-06 13:52 UTC

This package is auto-updated.

Last update: 2026-02-06 13:54:37 UTC


README

Tests Code Coverage

Test your Symfony / Api-Platform routes and controllers with symfony/http-client.

This package provides a test implementation of Symfony's HttpClientInterface that uses KernelBrowser internally, allowing you to test your HTTP endpoints as if you were making real HTTP requests, but without the overhead of running an actual HTTP server.

Compatible with both PHPUnit and Pest.

Example

// src/Controller/HealthController.php
namespace App\Controller;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Attribute\Route;

final readonly class HealthController 
{
    #[Route('/health')]
    public function __invoke(): JsonResponse {
        return new JsonResponse(['status' => '😎']);
    }
}

Pest

// tests/Controller/HealthControllerTest.php

use BenTools\TestHttpClient\TestHttpClient;

use function BenTools\Pest\Symfony\inject;

it('works', function () {
    $client  = inject(TestHttpClient::class); // <-- See package `bentools/pest-symfony-kernel`
    $response = $client->request('GET', '/health');
    
    expect($response)->toBeSuccessful()
        ->and($response)->toHaveStatusCode(200)
        ->and($response)->toHaveHeader('Content-Type', 'application/json')
        ->and($response)->toHaveJsonStructure(['status'])
        ->and($response['status'])->toBe('😎')
    ;
});

PHPUnit

// tests/Controller/HealthControllerTest.php
use BenTools\TestHttpClient\TestHttpClient;

class HealthControllerTest extends WebTestCase
{
    public function testHealth(): void
    {
        $client = static::getContainer()->get(TestHttpClient::class);
        $response = $client->request('GET', '/health');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertContains('application/json', $response->getHeaders()['content-type'] ?? '');
        $this->assertArrayHasKey('status', $response);
        $this->assertEquals('😎', $response['status']);
    }
}

Features

  • ✅ Implements HttpClientInterface - Drop-in replacement for real HTTP clients in tests
  • ✅ No HTTP server required - Uses Symfony's KernelBrowser under the hood
  • ✅ Fast integration tests - Test your API endpoints in milliseconds
  • ✅ Access to internals - Get the container, profiler, cookies, and more
  • ✅ Pest expectations included - Custom expectations for testing responses
  • ✅ Full HTTP feature support - Headers, authentication, JSON, query parameters, etc.

Installation

composer require --dev bentools/test-http-client

Symfony Bundle Integration

For Symfony applications, you can register the bundle to automatically wire the TestHttpClient service:

1. Register the Bundle

Add the bundle to your config/bundles.php (only in test environment):

// config/bundles.php
return [
    // ... other bundles
    BenTools\TestHttpClient\Bundle\TestHttpClientBundle::class => ['test' => true],
];

2. Use the Service

Once registered, the TestHttpClient service is automatically available in your test environment:

use BenTools\TestHttpClient\TestHttpClient;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class ApiTest extends WebTestCase
{
    public function testUsersList(): void
    {
        $client = static::getContainer()->get(TestHttpClient::class);
        $response = $client->request('GET', '/api/users');

        $this->assertSame(200, $response->getStatusCode());
    }
}

For Pest tests:

it('returns users list', function () {
    $client = container()->get(TestHttpClient::class);
    $response = $client->request('GET', '/api/users');

    expect($response)->toHaveStatusCode(200);
});

Note

If you prefer to instantiate TestHttpClient manually without registering the bundle, you can still do so as shown in the Quick Start section below.

Quick Start

With Pest

use BenTools\TestHttpClient\TestHttpClient;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

uses(WebTestCase::class);

it('returns users list', function () {
    $client = new TestHttpClient(static::createClient());
    $response = $client->request('GET', '/api/users');

    expect($response)
        ->toHaveStatusCode(200)
        ->toHaveJsonStructure()
        ->toHaveHeader('content-type', 'application/json');

    $data = $response->toArray();
    expect($data)->toHaveKey('users');
});

With PHPUnit

use BenTools\TestHttpClient\TestHttpClient;

public function testReturnsUsersList(): void
{
    $client = new TestHttpClient(static::createClient());
    $response = $client->request('GET', '/api/users');

    $this->assertSame(200, $response->getStatusCode());
    $this->assertArrayHasKey('users', $response->toArray());
}

Bearer Authentication

$response = $client->withAuthBearer('your-token-here')->request('GET', '/api/admin');

Access Cookies

$cookieJar = $client->kernelBrowser->getCookieJar();
$cookies = $cookieJar->all();

Performance Optimization

By default, Symfony reboots the kernel between requests. For better performance in tests with multiple requests:

$client = new TestHttpClient($kernelBrowser);
$client->kernelBrowser->disableReboot();

// Make multiple requests - kernel stays booted
$response1 = $client->request('GET', '/api/users');
$response2 = $client->request('GET', '/api/posts');
$response3 = $client->request('GET', '/api/comments');

Pest Expectations

If you're using Pest, the package includes custom expectations for testing responses:

use BenTools\TestHttpClient\TestHttpClient;

it('tests various response aspects', function () {
    $client = new TestHttpClient(static::createClient());
    $response = $client->request('GET', '/api/users');

    // Status code
    expect($response)->toHaveStatusCode(200);

    // Success (2xx)
    expect($response)->toBeSuccessful();

    // Client error (4xx)
    expect($response)->toBeClientError();

    // Server error (5xx)
    expect($response)->toBeServerError();

    // Headers
    expect($response)->toHaveHeader('content-type');
    expect($response)->toHaveHeader('cache-control', 'max-age=3600');

    // JSON
    expect($response)->toHaveJsonStructure();

    // JSON structure
    expect($response)->toHaveJsonStructure(['users', 'total', 'page']);
});

Available Expectations

  • toHaveStatusCode(int $code) - Assert status code
  • toBeSuccessful() - Assert 2xx status
  • toBeClientError() - Assert 4xx status
  • toBeServerError() - Assert 5xx status
  • toHaveHeader(string $name, ?string $value = null) - Assert header exists (optionally with value)
  • toHaveJsonStructure() - Assert content-type is JSON
  • toHaveJsonStructure(array $keys) - Assert JSON contains specific keys

Credits

Borrowed and adapted from Api-Platform's TestClient.

License

MIT.