A simple way to mock a client

Overview

Mocked Client

A simple way to mock a client

Install

Via Composer

$ composer require doppiogancio/mocked-client guzzlehttp/guzzle php-http/discovery

Note:

  • The package guzzlehttp/guzzle is not required, this package is compatible any http client that supports the PSR request/responses
  • The package php-http/discovery is not required, it is used to auto-discover the needed PSR factories (if you prefer you can provide the needed PSR factories manually)

Requirements

This version requires a minimum PHP version 7.4

How to mock a client

build() ); // Route with File $handlerBuilder->addRoute( $rb->new() ->withMethod('GET') ->withPath('/country/DE/json') ->withFileResponse(__DIR__ . '/fixtures/country.json') ->build() ); // Route with Conditional responses $handlerBuilder->addRoute( $cb->new() ->withMethod('GET') ->withPath('/country/') ->withConditionalResponse('code=de', new Response(200, [], '{"id":"+49","code":"DE","name":"Germany"}')) ->withConditionalFileResponse('code=it', __DIR__ . '/../fixtures/country_it.json') ->withConditionalStringResponse('code=fr', '{"id":"+33","code":"FR","name":"France"}') ->build() ); $clientBuilder = new MockedGuzzleClientBuilder($handlerBuilder); return $clientBuilder->build(); ">
use DoppioGancio\MockedClient\HandlerBuilder;
use DoppioGancio\MockedClient\MockedGuzzleClientBuilder;
use DoppioGancio\MockedClient\Route\ConditionalRouteBuilder;
use DoppioGancio\MockedClient\Route\RouteBuilder;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response;
use Http\Discovery\Psr17FactoryDiscovery;
// ... more imports

$handlerBuilder = new HandlerBuilder(
    Psr17FactoryDiscovery::findServerRequestFactory(),
);

$cb = new ConditionalRouteBuilder(
    Psr17FactoryDiscovery::findResponseFactory(),
    Psr17FactoryDiscovery::findStreamFactory(),
);

$rb = new RouteBuilder(
    Psr17FactoryDiscovery::findResponseFactory(),
    Psr17FactoryDiscovery::findStreamFactory(),
);

// Route with Response
$handlerBuilder->addRoute(
    $rb->new()
        ->withMethod('GET')
        ->withPath('/country/IT')
        ->withResponse(new Response(200, [], '{"id":"+39","code":"IT","name":"Italy"}'))
        ->build()
);

// Route with File
$handlerBuilder->addRoute(
    $rb->new()
        ->withMethod('GET')
        ->withPath('/country/DE/json')
        ->withFileResponse(__DIR__ . '/fixtures/country.json')
        ->build()
);

// Route with Conditional responses
$handlerBuilder->addRoute(
    $cb->new()
        ->withMethod('GET')
        ->withPath('/country/')
        ->withConditionalResponse('code=de', new Response(200, [], '{"id":"+49","code":"DE","name":"Germany"}'))
        ->withConditionalFileResponse('code=it', __DIR__ . '/../fixtures/country_it.json')
        ->withConditionalStringResponse('code=fr', '{"id":"+33","code":"FR","name":"France"}')
        ->build()
);

$clientBuilder = new MockedGuzzleClientBuilder($handlerBuilder);

return $clientBuilder->build();

How to use the client

$response = $client->request('GET', '/country/DE/json');
$body = (string) $response->getBody();
$country = json_decode($body, true);

print_r($country);

// will return
Array
(
    [id] => +49
    [code] => DE
    [name] => Germany
)

Some recommendations...

If you are testing a component that uses a client, don't worry, instantiate a mocked client without routes.

$builder = new HandlerBuilder(
    Psr17FactoryDiscovery::findResponseFactory(),
    Psr17FactoryDiscovery::findServerRequestFactory(),
    Psr17FactoryDiscovery::findStreamFactory(),
);

// Add here the routes ...

$clientBuilder = new MockedGuzzleClientBuilder($builder);
$client = $clientBuilder->build();

inject it in the kernel container if needed

self::$container->set('eight_points_guzzle.client.william', $client);

Run the test: the test will fail, but it will suggest you the route that is missing. By doing this, it will only specify the needed routes.

An example:

DoppioGancio\MockedClient\Exception\RouteNotFound : Mocked route GET /admin/dashboard not found

To mock for example an error response:

$handlerBuilder->addRouteWithResponse('GET', '/admin/dashboard', new Response(401));
You might also like...
Validate your input data in a simple way, an easy way and right way. no framework required. For simple or large. project.

wepesi_validation this module will help to do your own input validation from http request POST or GET. INTEGRATION The integration is the simple thing

Attempting to create an intelligent mock of the Google API PHP Client for unit and functional testing

google-api-php-client-mock A small scale intelligent mock of the Google API PHP Client for unit and functional testing. Overview This is intended to m

Very simple mock HTTP Server for testing Restful API, running via Docker.

httpdock Very simple mock HTTP Server for testing Restful API, running via Docker. Start Server Starting this server via command: docker run -ti -d -p

Mock HTTP requests on the server side in your PHP unit tests

HTTP Mock for PHP Mock HTTP requests on the server side in your PHP unit tests. HTTP Mock for PHP mocks the server side of an HTTP request to allow in

Mock built-in PHP functions (e.g. time(), exec() or rand())

PHP-Mock: mocking built-in PHP functions PHP-Mock is a testing library which mocks non deterministic built-in PHP functions like time() or rand(). Thi

vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with any unit test framework, like PHPUnit or SimpleTest.

vfsStream vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with

Mock authentication for CodeIgniter 4

Tatter\Imposter Mock authentication for CodeIgniter

Mock implementation of the Translation package, for testing with PHPUnit

PoP Translation - Mock Mock implementation of the Translation package, for testing with PHPUnit Install Via Composer composer require getpop/translati

SimpleTest is a framework for unit testing, web site testing and mock objects for PHP

SimpleTest SimpleTest is a framework for unit testing, web site testing and mock objects for PHP. Installation Downloads All downloads are stored on G

Mockery - Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library

Mockery Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its c

MOP is a php query handling and manipulation library providing easy and reliable way to manipulate query and get result in a fastest way
MOP is a php query handling and manipulation library providing easy and reliable way to manipulate query and get result in a fastest way

Mysql Optimizer mysql optimizer also known as MOP is a php query handling and manipulation library providing easy and reliable way to manipulate query

MOP is a php query handling and manipulation library providing easy and reliable way to manipulate query and get result in a fastest way. ( WEBSITE VERSION )
MOP is a php query handling and manipulation library providing easy and reliable way to manipulate query and get result in a fastest way. ( WEBSITE VERSION )

Mysql Optimizer mysql optimizer also known as MOP is a php query handling and manipulation library providing easy and reliable way to manipulate query

A simple wrapper for PHP Intervention Library to provide a more simple interface and convenient way to convert images to webp

This package is a simple wrapper for PHP Intervention Library to provide a more simple interface and convenient way to convert images to webp - next generation format - extension, and resize them to render only needed sizes.

Simple-podcast-generator - ๐Ÿ‘‰ A very simple way to host your podcast files and generate the RSS Podcast feed ๐ŸŽ™

Podcast RSS Feed Generator A very simple way to host your podcast files and generate the RSS Podcast feed ๐ŸŽ™ ๐Ÿ“– Contents Summary Requirements Installa

 amadeus-ws-client: PHP client for the Amadeus GDS SOAP Web Service interface
amadeus-ws-client: PHP client for the Amadeus GDS SOAP Web Service interface

amadeus-ws-client: PHP client for the Amadeus GDS SOAP Web Service interface This client library provides access to the Amadeus GDS SOAP Web Service i

The Salla OAuth Client library is designed to provide client applications with secure delegated access to Salla Merchant stores.
The Salla OAuth Client library is designed to provide client applications with secure delegated access to Salla Merchant stores.

Salla Provider for OAuth 2.0 Client This package provides Salla OAuth 2.0 support for the PHP League's OAuth 2.0 Client. To use this package, it will

Google-api-php-client - A PHP client library for accessing Google APIs

Google APIs Client Library for PHP Reference Docs https://googleapis.github.io/google-api-php-client/main/ License Apache 2.0 The Google API Client Li

PHP Kafka client is used in PHP-FPM and Swoole. PHP Kafka client supports 50 APIs, which might be one that supports the most message types ever.

longlang/phpkafka Introduction English | ็ฎ€ไฝ“ไธญๆ–‡ PHP Kafka client is used in PHP-FPM and Swoole. The communication protocol is based on the JSON file in

Comments
  • Route builder

    Route builder

    Main goal

    My main goal was to allow a route, where the response is based on "query string".

    A possible solution

    The only way to accomplish this was to add a route with a handler.

    $builder->addRoute(
        'GET', '/country/IT', static function (ServerRequestInterface $request): Response {
            if (...) {
                return new Response(200, [], '{"id":"+39","code":"IT","name":"Italy"}');
            }
    
            if (...) {
                return new Response(200, [], '{"id":"+49","code":"DE","name":"Germany"}');
            }
    
           ....
        }
    );
    

    Pros

    Already possible

    Cons

    1. There is no way to build response out of files/strings
    2. A lot of repetitive code

    An alternative solution

    A route builder could give the possibility to define the route incrementally (add the method, then the HTTP status, then the response, and so on...).

    $route = $builder
                ->withMethod('GET')
                ->withPath('/country')
                ->withResponse(new Response(123))
                ->build();
    

    Add this point I should consider a method to add a conditional response, something like:

    ->withConditionalResponse('page=2&code=it', new Response(200, [], '{"id":"+39","code":"IT","name":"Italy"}'))
    

    Since I don't want the developer to use at the same time withResponse and withConditionalResponse I created to separated builders:

    1. RouteBuilder
    2. ConditionalRouteBuilder

    Final solution

    It's not important how many parameters the request has in the query string, and not even the order, each conditional-response will try to match only the specified params/values.

    $builder = new ConditionalRouteBuilder(
                Psr17FactoryDiscovery::findResponseFactory(),
                Psr17FactoryDiscovery::findStreamFactory(),
            );
    
            $route = $builder->withMethod('GET')
                ->withPath('/country')
                ->withConditionalResponse('page=2&code=it', new Response(201))
                ->withConditionalResponse('code=de', new Response(301))
                ->withConditionalResponse('page=4', new Response(401))
                ->withDefaultNotFoundResponse(new Response(123))
                ->build();
    
            $response = $route->getHandler()(new Request('GET', '/country?nonce=12345&code=fr&page=3'));
    
    opened by doppiogancio 3
  • Better debug mode

    Better debug mode

    The debug could also show each request and answer, including headers as follows:

    > GET /get HTTP/1.1
    Host: httpbin.org
    User-Agent: Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8
    
    < HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *
    Content-Type: application/json
    Date: Tue, 25 Mar 2014 03:53:27 GMT
    Server: gunicorn/0.17.4
    Content-Length: 270
    Connection: keep-alive
    
    {
      "headers": {
        "Connection": "close",
        "X-Request-Id": "3d0f7d5c-c937-4394-8248-2b8e03fcccdb",
        "User-Agent": "Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8",
        "Host": "httpbin.org"
      },
      "origin": "76.104.247.1",
      "args": {},
      "url": "http://httpbin.org/get"
    }
    
    > HEAD /get HTTP/1.1
    Host: httpbin.org
    User-Agent: Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8
    
    < HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *
    Content-length: 270
    Content-Type: application/json
    Date: Tue, 25 Mar 2014 03:53:27 GMT
    Server: gunicorn/0.17.4
    Connection: keep-alive
    
    opened by doppiogancio 1
  • Response with timeout

    Response with timeout

    Goal

    The goal is to simulate a timeout for a certain request in a test.

    First solution: sleep for n seconds

    A handler with that "sleep" for n seconds, where n > default timeout, I thought it was enough, but apparently, in case of timeout, the client will throw an error.

    Second solution: a response with an exception

    Having a more generic route with an exception will cover also the timeout scenario. This is a specific example for guzzle:

    $rb->new()
             ->withMethod('GET')
             ->withPath('/slow/api')
             ->withException(new ConnectException(
                      'Timed out after 30 seconds',
                      new Request('GET', '/slow/api')
             ))
             ->build()
    
    opened by doppiogancio 0
  • Add relative route support

    Add relative route support

    League's $router->map always rewrites the route to an absolute path. I've added that logic to the createServerRequest so relative routes can now be supported.

    opened by Sauerbrei 1
Releases(v2.0.7)
  • v2.0.7(Aug 10, 2022)

    What's Changed

    • Guzzle Exceptions v2 by @doppiogancio in https://github.com/doppiogancio/mocked-client/pull/19

    Full Changelog: https://github.com/doppiogancio/mocked-client/compare/v2.0.6...v2.0.7

    Source code(tar.gz)
    Source code(zip)
  • v2.0.6(Jul 25, 2022)

    What's Changed

    • Route Not Found proper Exception by @doppiogancio in https://github.com/doppiogancio/mocked-client/pull/17

    Full Changelog: https://github.com/doppiogancio/mocked-client/compare/v2.0.5...v2.0.6

    Source code(tar.gz)
    Source code(zip)
  • v2.0.5(Jul 25, 2022)

    What's Changed

    • Added previous exception to NotFound exception by @doppiogancio in https://github.com/doppiogancio/mocked-client/pull/16

    Full Changelog: https://github.com/doppiogancio/mocked-client/compare/v2.0.3...v2.0.5

    Source code(tar.gz)
    Source code(zip)
  • v3.1.2(Jul 21, 2022)

    What's Changed

    • Routes added to RouteNotFound by @doppiogancio in https://github.com/doppiogancio/mocked-client/pull/13

    Full Changelog: https://github.com/doppiogancio/mocked-client/compare/v3.1.1...v3.1.2

    Source code(tar.gz)
    Source code(zip)
  • v2.0.4(Jul 21, 2022)

    What's Changed

    • Rolling back RouteNotFound routes by @doppiogancio in https://github.com/doppiogancio/mocked-client/pull/15

    Full Changelog: https://github.com/doppiogancio/mocked-client/compare/v2.0.3...v2.0.4

    Source code(tar.gz)
    Source code(zip)
  • v2.0.3(Jul 21, 2022)

    What's Changed

    • Added routes to RouteNotFound exception by @doppiogancio in https://github.com/doppiogancio/mocked-client/pull/14

    Full Changelog: https://github.com/doppiogancio/mocked-client/compare/v2.0.2...v2.0.3

    Source code(tar.gz)
    Source code(zip)
  • v3.1.1(Jun 25, 2022)

    What's Changed

    • Added packagist badges to README by @doppiogancio in https://github.com/doppiogancio/mocked-client/pull/12

    Full Changelog: https://github.com/doppiogancio/mocked-client/compare/v3.1.0...v3.1.1

    Source code(tar.gz)
    Source code(zip)
  • v3.1.0(Apr 15, 2022)

    What's Changed

    • Response with timeout by @doppiogancio in https://github.com/doppiogancio/mocked-client/pull/8
    • Conditional route default response by @doppiogancio in https://github.com/doppiogancio/mocked-client/pull/11

    Full Changelog: https://github.com/doppiogancio/mocked-client/compare/v3.0.1...v3.1.0

    Source code(tar.gz)
    Source code(zip)
  • v2.0.2(Apr 15, 2022)

    What's Changed

    • Conditional response for v2 by @doppiogancio in https://github.com/doppiogancio/mocked-client/pull/9

    Full Changelog: https://github.com/doppiogancio/mocked-client/compare/v2.0.1...v2.0.2

    Source code(tar.gz)
    Source code(zip)
  • v3.0.1(Sep 28, 2021)

  • v2.0.1(Aug 23, 2021)

Owner
Fabrizio Gargiulo
Fabrizio Gargiulo
Very simple mock HTTP Server for testing Restful API, running via Docker.

httpdock Very simple mock HTTP Server for testing Restful API, running via Docker. Start Server Starting this server via command: docker run -ti -d -p

Vo Duy Tuan 4 Dec 24, 2021
Mock HTTP requests on the server side in your PHP unit tests

HTTP Mock for PHP Mock HTTP requests on the server side in your PHP unit tests. HTTP Mock for PHP mocks the server side of an HTTP request to allow in

InterNations GmbH 386 Dec 27, 2022
Mock built-in PHP functions (e.g. time(), exec() or rand())

PHP-Mock: mocking built-in PHP functions PHP-Mock is a testing library which mocks non deterministic built-in PHP functions like time() or rand(). Thi

null 331 Jan 3, 2023
vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with any unit test framework, like PHPUnit or SimpleTest.

vfsStream vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with

null 1.4k Dec 23, 2022
Mock implementation of the Translation package, for testing with PHPUnit

PoP Translation - Mock Mock implementation of the Translation package, for testing with PHPUnit Install Via Composer composer require getpop/translati

PoP 1 Jan 13, 2022
SimpleTest is a framework for unit testing, web site testing and mock objects for PHP

SimpleTest SimpleTest is a framework for unit testing, web site testing and mock objects for PHP. Installation Downloads All downloads are stored on G

SimpleTest 147 Jun 20, 2022
Mockery - Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library

Mockery Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its c

Mockery 10.3k Jan 1, 2023
PHP client for Selenium/WebDriver protocol. Previously facebook/php-webdriver

Php-webdriver library is PHP language binding for Selenium WebDriver, which allows you to control web browsers from PHP.

php-webdriver 4.7k Jan 3, 2023
The modern, simple and intuitive PHP unit testing framework.

atoum PHP version atoum version 5.3 -> 5.6 1.x -> 3.x 7.2 -> 8.x 4.x (current) A simple, modern and intuitive unit testing framework for PHP! Just lik

atoum 1.4k Nov 29, 2022
This is a simple invoice page that user can add product to his/her basket with qty.

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

null 1 Nov 22, 2021