Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mock Webserver Laravel Package

donatj/mock-webserver

Lightweight PHP mock web server for tests and local development. Spin up an HTTP server on a random port, enqueue canned responses, inspect received requests, and simulate endpoints reliably. Handy for integration tests without external services.

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation Update Composer to ensure compatibility with PHP 7.2+ (now mandatory due to security updates):

    composer require --dev donatj/mock-webserver:^2.10.0
    

    No manual service provider registration is needed—the package is auto-discovered.

  2. Basic Usage Start a mock server in a test (PHP 7.2+ required):

    use Donatj\MockWebserver\MockWebserver;
    
    public function test_example()
    {
        $server = new MockWebserver();
        $server->start(); // Uses PHP_BINARY internally (resolves PATH issues)
    
        // Get the mock server URL
        $response = Http::get($server->getUrl('/api/test'));
        $this->assertEquals(200, $response->status());
    }
    
  3. Key Entry Points

    • MockWebserver class: Core class for managing routes, responses, and server state.
    • MockWebserver::start(): Launches the server on a random port (now more reliable with PHP_BINARY fix).
    • MockWebserver::getUrl(string $path): Generates a full URL for testing.
    • MockWebserver::addRoute(): Registers mock routes (GET, POST, etc.).

Implementation Patterns

Common Workflows

1. Mocking API Responses

$server = new MockWebserver();
$server->start();

// Mock a GET endpoint
$server->addRoute('GET', '/api/users', fn() =>
    response()->json(['id' => 1, 'name' => 'John Doe'])
);

$response = Http::get($server->getUrl('/api/users'));
$this->assertJson($response->json());

2. Simulating POST/PUT Requests with Payloads

$server->addRoute('POST', '/api/users', function ($request) {
    $data = json_decode($request->getBody(), true);
    return response()->json(['success' => true, 'data' => $data]);
});

Http::post($server->getUrl('/api/users'), ['name' => 'Jane']);

3. Testing File Uploads

$server->addRoute('POST', '/api/upload', function ($request) {
    $file = $request->file('file');
    return response()->json(['filename' => $file->getClientOriginalName()]);
});

Http::post($server->getUrl('/api/upload'), [
    'file' => UploadedFile::fake()->create('test.txt', 100),
]);

4. Integration with Laravel HTTP Tests

public function test_login_flow()
{
    $server = new MockWebserver();
    $server->start();

    $server->addRoute('POST', '/api/login', fn() =>
        response()->json(['token' => 'mock-token'])
    );

    $response = Http::post($server->getUrl('/api/login'), ['email' => 'test@example.com']);
    $this->assertEquals('mock-token', $response->json('token'));
}

5. Dynamic Route Matching

Use regex or closures for flexible routing:

$server->addRoute('GET', '/api/users/{id}', function ($request) {
    $id = $request->route('id');
    return response()->json(['id' => $id]);
});

Advanced Patterns

1. Reusing Mock Servers Across Tests

Use a static instance or dependency injection:

// In a test trait
protected $mockServer;

protected function setUp(): void
{
    $this->mockServer = new MockWebserver();
    $this->mockServer->start();
}

protected function tearDown(): void
{
    $this->mockServer->stop(); // Critical: Frees ports
}

2. Mocking External Services

Replace third-party APIs (e.g., Stripe, PayPal) with local mocks:

$server->addRoute('POST', '/webhooks/stripe', function () {
    return response()->json(['type' => 'payment_intent.succeeded']);
});

3. Testing Middleware

Simulate middleware behavior in mock responses:

$server->addRoute('GET', '/api/protected', function () {
    if (!auth()->check()) {
        return response()->json(['error' => 'Unauthorized'], 401);
    }
    return response()->json(['data' => 'secret']);
});

Gotchas and Tips

Critical Updates (v2.10.0)

  1. PHP 7.2+ Mandatory

    • Breaking Change: PHP <7.2 is unsupported due to CVE-2026-24765.
    • Fix: Update your project:
      composer require php:^7.2 --dev
      
    • Workaround: Downgrade to v2.9.0 if stuck on older PHP (not recommended).
  2. PHP_BINARY Fix for PATH Issues

    • Issue: Server failed to start if PHP wasn’t in PATH (e.g., macOS 14.3+).
    • Solution: The package now uses PHP_BINARY internally. If issues persist:
      putenv('PHP_BINARY=' . escapeshellarg('/usr/local/bin/php'));
      
  3. Port Conflicts

    • Tip: Explicitly set a port in CI to avoid collisions:
      $server->setPort(8080);
      

Debugging Tips

  1. Enable Verbose Logging

    $server->setVerbose(true); // Logs server startup/shutdown
    
  2. Inspect Requests Add a debug route:

    $server->addRoute('*', '/debug', function ($request) {
        \Log::debug('Request:', [
            'method' => $request->method(),
            'path' => $request->path(),
            'headers' => $request->headers(),
            'body' => $request->getBody(),
        ]);
    });
    
  3. Check Port Usage If tests hang, verify no stale processes:

    lsof -i :<port>
    
  4. CORS Headers The mock server does not enforce CORS by default. Add headers manually:

    $server->addRoute('GET', '/api/data', function () {
        return response()
            ->json(['data' => 'test'])
            ->header('Access-Control-Allow-Origin', '*');
    });
    

Extension Points

  1. Custom Response Factories Extend MockWebserver for reusable helpers:

    class CustomMockWebserver extends MockWebserver
    {
        public function jsonResponse($data, $status = 200)
        {
            $this->addRoute('GET', '/api/json', fn() =>
                response()->json($data, $status)
            );
        }
    }
    
  2. Middleware Simulation Override route handling:

    $server->addRoute('GET', '/api/middleware', function ($request) {
        if ($request->header('X-API-KEY') !== 'secret') {
            return response()->json(['error' => 'Unauthorized'], 403);
        }
        // ...
    });
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
cadot.eu/make
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky