neur0toxine / pock
PSR-18 兼容的 HTTP 模拟库
v0.12.2
2023-10-03 09:45 UTC
Requires
- php: >=7.2.0
- ext-json: *
- nyholm/psr7: ^1.4
- php-http/httplug: ^1.0 || ^2.0
- psr/http-client: ^1.0
- psr/http-message: ^1.0 || ^2.0
- riverline/multipart-parser: ^2.0
Requires (Dev)
- dealerdirect/phpcodesniffer-composer-installer: ^0.7.1
- jms/serializer: ^2 | ^3.17
- php-http/multipart-stream-builder: ^1.2
- phpcompatibility/php-compatibility: ^9.3
- phpmd/phpmd: ^2.12
- phpstan/phpstan: ^1.5
- squizlabs/php_codesniffer: ^3.6
- symfony/http-client: ^5.3
- symfony/phpunit-bridge: ^5.2
- symfony/property-access: ^5.2
- symfony/serializer: ^5.2
Provides
README
pock
易于使用的 HTTP 模拟解决方案,兼容 PSR-18 和 HTTPlug。
项目仍处于早期开发阶段。API 随时间可能会变化,但我将尽量避免引入破坏性更改。您可以在这里找到自动生成的文档或查看示例。模拟构建的 API 可以在这里找到,响应构建的 API(从 PockBuilder::reply
调用返回)可以在这里找到。
示例
模拟 JSON API 路由,使用基本认证,以 JSON 格式回复。
use Pock\Enum\RequestMethod; use Pock\Enum\RequestScheme; use Pock\PockBuilder; $builder = new PockBuilder(); $builder->matchMethod(RequestMethod::GET) ->matchScheme(RequestScheme::HTTPS) ->matchHost('example.com') ->matchPath('/api/v1/users') ->matchHeaders([ 'Content-Type' => 'application/json', 'Authorization' => 'Basic YWxhZGRpbjpvcGVuc2VzYW1l' ]) ->reply(200) ->withHeader('Content-Type', 'application/json') ->withJson([ [ 'name' => 'John Doe', 'username' => 'john', 'email' => '[email protected]' ], [ 'name' => 'Jane Doe', 'username' => 'jane', 'email' => '[email protected]' ], ]); // Pass PSR-18 compatible client to the API client. $client = new MysteriousApiClient($builder->getClient()); $client->setCredentials('username', 'password'); // Receive mock response. $response = $client->getUsers();
相同的模拟,但使用模型!此外,代码本身也稍微短一些。
use Pock\Enum\RequestMethod; use Pock\PockBuilder; $builder = new PockBuilder(); $builder->matchMethod(RequestMethod::GET) ->matchUri('https://example.com/api/v1/users') ->matchHeaders([ 'Content-Type' => 'application/json', 'Authorization' => 'Basic YWxhZGRpbjpvcGVuc2VzYW1l' ]) ->reply(200) ->withHeader('Content-Type', 'application/json') ->withJson([ // We're assuming here that MysteriousUser's constructor can receive an initial values. new MysteriousUser('John Doe', 'john', '[email protected]'), new MysteriousUser('Jane Doe', 'jane', '[email protected]'), ]); // Pass PSR-18 compatible client to the API client. $client = new MysteriousApiClient($builder->getClient()); $client->setCredentials('username', 'password'); // Receive mock response. $response = $client->getUsers();
由于 pock 可以在底层使用第三方序列化器,因此可以使用 DTO 模拟响应。
序列化器支持
pock 默认支持 JMS 序列化器和 Symfony 序列化器。可用的序列化器将自动实例化。它将用于序列化模拟中的请求和响应,这意味着您可以实际将整个 DTO 传递到相应的函数中(例如,将 matchJsonBody
作为断言或 withJsonBody
生成响应体)。
默认情况下,JMS 序列化器比 Symfony 序列化器具有更高的优先级。如果您想在运行测试之前(bootstrap.php
)覆盖默认行为,可以使用以下方法。
use Pock\Factory\JsonSerializerFactory; use Pock\Factory\XmlSerializerFactory; use Pock\Serializer\SymfonySerializerAdapter; use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Serializer; $encoders = [new XmlEncoder(), new JsonEncoder()]; $normalizers = [new ObjectNormalizer()]; $serializer = new SymfonySerializerAdapter(new Serializer($normalizers, $encoders)); JsonSerializerFactory::setSerializer($serializer); XmlSerializerFactory::setSerializer($serializer);
要使用不受支持的序列化器,您应该创建一个实现 Pock\Serializer\SerializerInterface
的适配器。
迈向稳定之路
-
at(N)
- 仅在第 N 次调用时执行模拟。 -
always()
- 总是执行此模拟(删除模拟过期时间)。 - 将
UniversalMockException
分离成几个异常(PockClientException
、PockNetworkException
等)。 - 添加更轻松抛出前述列表中异常的方法。
-
replyWithCallback
- 使用指定的回调回复。 -
replyWithFactory
- 使用指定的响应工厂(提供相应的接口)回复。 - 使用
DOMDocument
比较 XML 主体,如果出现问题,则回退到文本比较。 - 正则表达式匹配器用于主体、查询、URI 和路径。
- 表单数据主体匹配器(部分和精确)
- 多部分表单主体匹配器(类似于回调匹配器,但将主体解析为多部分表单数据)
- 破坏性更改:将序列化器装饰器重命名为序列化器适配器。
- 模拟请求的真实网络响应。
- 支持
symfony/http-client
。 - 记录一切(如果可行,附带示例)。