PHP code example of qoliber / servermock

1. Go to this page and download the library: Download qoliber/servermock library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

qoliber / servermock example snippets


use Qoliber\ServerMock\Mock;
use Qoliber\ServerMock\MockServer;

// Start a mock server on a random port
$server = MockServer::start();

// Define a stub
Mock::get('/api/users/1')
    ->respondJson(['id' => 1, 'name' => 'John Doe'])
    ->mount($server);

// Make requests against it
$response = file_get_contents($server->url('/api/users/1'));
// Returns: {"id":1,"name":"John Doe"}

// Clean up
$server->shutdown();

$server->configure([
    Mock::get('/api/users')->respondJson(['users' => []]),
    Mock::get('/api/products')->respondJson(['products' => ['SKU001']]),
    Mock::post('/api/orders')->respondJson(['orderId' => '12345'], 201),
]);

use Qoliber\ServerMock\Scenario;

$checkoutScenario = Scenario::create('checkout')
    ->stub(Mock::get('/api/cart')->respondJson(['items' => [], 'total' => 0]))
    ->stub(Mock::post('/api/cart/add')->respondJson(['success' => true]))
    ->stub(Mock::post('/api/checkout')->respondJson(['orderId' => 'ORD-001']));

$server->applyScenario($checkoutScenario);

$scenario = Scenario::create('user-flow');
$scenario->get('/api/profile')->respondJson(['name' => 'John']);
$scenario->post('/api/update')->respondJson(['updated' => true]);
$scenario->applyTo($server);

$server->loadFromFile('fixtures/api-stubs.yaml');  // Auto-detects YAML
$server->loadFromFile('fixtures/api-stubs.json');  // Auto-detects JSON

$server->loadFromJson('fixtures/stubs.json');

$server->loadFromYaml('fixtures/stubs.yaml');

$server->loadFromToml('fixtures/stubs.toml');

$server->loadFromPhp('fixtures/stubs.php');


return [
    'stubs' => [
        [
            'method' => 'GET',
            'path' => '/api/config',
            'response' => [
                'body' => json_encode(['timestamp' => time()]),
            ],
        ],
    ],
];

$server->loadFromArray([
    'stubs' => [
        [
            'method' => 'GET',
            'path' => '/api/users',
            'response' => ['body' => '[]'],
        ],
        [
            'method' => 'GET',
            'pathRegex' => '#^/api/users/\d+$#',
            'response' => ['body' => '{"id": "matched"}'],
        ],
    ],
]);

use Qoliber\ServerMock\ServerMockTestCase;
use Qoliber\ServerMock\Mock;

class MyIntegrationTest extends ServerMockTestCase
{
    public function testPaymentGateway(): void
    {
        Mock::post('/v1/charges')
            ->respondJson(['id' => 'ch_123', 'status' => 'succeeded'], 201)
            ->mount($this->mockServer);

        $paymentService = new PaymentService($this->getMockServerUri());
        $result = $paymentService->charge(1000, 'usd');

        $this->assertTrue($result->isSuccessful());
    }
}

use PHPUnit\Framework\TestCase;
use Qoliber\ServerMock\ServerMockTrait;
use Qoliber\ServerMock\Mock;

class MyTest extends TestCase
{
    use ServerMockTrait;

    protected function setUp(): void
    {
        parent::setUp();
        $this->setUpServerMock();
    }

    protected function tearDown(): void
    {
        $this->tearDownServerMock();
        parent::tearDown();
    }
}

Mock::post('/api/echo')
    ->respondJsonTemplate('{"path": "{{request.path}}", "method": "{{request.method}}"}')
    ->mount($server);

Mock::post('/api/users')
    ->respondJsonTemplate('{"id": "{{uuid}}", "name": "{{request.jsonBody.name}}"}')
    ->mount($server);

Mock::graphql()
    ->withOperationName('GetUser')
    ->respondGraphQL(['user' => ['id' => '1', 'name' => 'John']])
    ->mount($server);

Mock::graphql()
    ->withMutation()
    ->withQueryContaining('createUser')
    ->respondGraphQL(['createUser' => ['id' => '123']])
    ->mount($server);

Mock::graphql()
    ->withVariable('userId', '999')
    ->respondGraphQL(['user' => ['id' => '999']])
    ->mount($server);

// Error responses
Mock::graphql()
    ->withOperationName('FailingOp')
    ->respondGraphQLError('Something went wrong', 'INTERNAL_ERROR')
    ->mount($server);

Mock::get('/exact/path')
Mock::getMatching('#^/users/\d+$#')  // Regex

use Qoliber\ServerMock\Matcher\PathMatcher;
Mock::given(new MethodMatcher('GET'))
    ->and(PathMatcher::startsWith('/api/'))

Mock::get('/secured')
    ->withHeader('Authorization')  // Header exists
    ->withHeader('X-API-Key', 'secret')  // Header equals value

Mock::get('/search')
    ->withQueryParam('q')  // Param exists
    ->withQueryParam('page', '1')  // Param equals value

Mock::post('/echo')->withBody('exact content')
Mock::post('/search')->withBodyContaining('important')
Mock::post('/validate')->withBodyMatching('/^order-\d{4}$/')
Mock::post('/api/order')->withJsonBody(['type' => 'premium'])
Mock::post('/webhook')->withJsonPath('event.type', 'payment.success')

use Qoliber\ServerMock\Response;

Mock::get('/ok')->respondOk('Body text')
Mock::get('/not-found')->respondNotFound()
Mock::get('/error')->respondServerError()
Mock::get('/json')->respondJson(['key' => 'value'])
Mock::post('/create')->respondJson(['id' => 1], 201)

Mock::get('/custom')
    ->respondWith(
        Response::create(201)
            ->withHeader('X-Custom', 'value')
            ->withBody('{"custom": true}')
    )

use Qoliber\ServerMock\ResponseSequence;

$sequence = ResponseSequence::create()
    ->thenJson(['status' => 'pending'])
    ->thenJson(['status' => 'processing'])
    ->thenJson(['status' => 'complete']);

Mock::get('/job/status')
    ->respondWithSequence($sequence)
    ->mount($server);

// With repeat
$sequence = ResponseSequence::create()
    ->thenJson(['cycle' => 1])
    ->thenJson(['cycle' => 2])
    ->repeat();  // Loops: 1, 2, 1, 2...

Mock::get('/slow-endpoint')
    ->respondOk('Finally!')
    ->withDelay(2000)  // 2 second delay
    ->mount($server);

Mock::get('/api/resource')
    ->respondJson(['source' => 'specific'])
    ->withPriority(10)  // Higher priority wins
    ->mount($server);

$stub = Mock::get('/tracked')->respondOk()->mount($server);

$client->get($server->url('/tracked'));
$client->get($server->url('/tracked'));

$requests = $server->getRecordedRequests();
$count = $server->getRequestCount();  // 2

$server->assertCalled($stub);     // At least once
$server->assertNotCalled($stub);  // Never called
$server->verify($stub, 2);        // Exactly 2 times

use Qoliber\ServerMock\State\StateMachine;

$scenario = StateMachine::create('order-flow')
    ->initialState('empty')
    ->when('empty')
        ->on(Mock::post('/cart/add'))
        ->respondJson(['success' => true, 'itemCount' => 1])
        ->transitionTo('has-items')
    ->when('has-items')
        ->on(Mock::get('/cart'))
        ->respondJson(['items' => ['SKU-001']])
        ->stay()  // Stay in current state
    ->when('has-items')
        ->on(Mock::post('/checkout'))
        ->respondJson(['orderId' => 'ORD-123'])
        ->transitionTo('ordered')
    ->when('ordered')
        ->on(Mock::get('/order/ORD-123'))
        ->respondJson(['status' => 'confirmed'])
    ->getMachine();

$server->addStateMachine($scenario);

// Now requests trigger state transitions
$client->post('/cart/add');  // empty -> has-items
$client->get('/cart');       // stays in has-items
$client->post('/checkout');  // has-items -> ordered

// Inspect and control state
$state = $server->getScenarioState('order-flow');  // 'ordered'
$server->setScenarioState('order-flow', 'empty');  // Reset manually
$server->resetScenario('order-flow');              // Reset to initial
$server->resetAllScenarios();                      // Reset all

use Qoliber\ServerMock\Fault\Fault;

// Random server errors (500) with 30% probability
Mock::get('/api/flaky')
    ->withFault(Fault::randomServerError(0.3, 'Service temporarily unavailable'))
    ->respondJson(['data' => 'ok'])
    ->mount($server);

// Fixed delay (simulates slow network)
Mock::get('/api/slow')
    ->withFault(Fault::fixedDelay(500))  // 500ms delay
    ->respondJson(['data' => 'slow'])
    ->mount($server);

// Random delay between min and max
Mock::get('/api/variable')
    ->withFault(Fault::randomDelay(100, 1000))  // 100-1000ms
    ->respondJson(['data' => 'variable'])
    ->mount($server);

// Connection reset (simulates dropped connection)
Mock::get('/api/unstable')
    ->withFault(Fault::connectionReset(0.2))  // 20% chance
    ->respondJson(['data' => 'ok'])
    ->mount($server);

// Empty response (simulates truncated response)
Mock::get('/api/broken')
    ->withFault(Fault::emptyResponse(0.1))
    ->respondJson(['data' => 'ok'])
    ->mount($server);

// Malformed JSON (simulates corrupt response)
Mock::get('/api/corrupt')
    ->withFault(Fault::malformedJson(0.1))
    ->respondJson(['data' => 'ok'])
    ->mount($server);

// Timeout (simulates request timeout)
Mock::get('/api/timeout')
    ->withFault(Fault::timeout(0.1, 30000))  // 10% chance, 30s delay
    ->respondJson(['data' => 'ok'])
    ->mount($server);

// Chain multiple faults
Mock::get('/api/chaos')
    ->withFault(Fault::chain(
        Fault::randomDelay(50, 200),
        Fault::randomServerError(0.1)
    ))
    ->respondJson(['data' => 'ok'])
    ->mount($server);

$server->enableProxy('https://api.example.com', record: true);

// Requests that don't match any stub are forwarded
// With record: true, responses are recorded for later inspection
$recordings = $server->getProxyRecordings();

$server->disableProxy();