mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-12-02 11:48:08 +08:00
Added testing component.
This commit is contained in:
parent
ab9296fcc4
commit
f5cfeee1a5
63
src/testing/co-phpunit
Executable file
63
src/testing/co-phpunit
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
\Swoole\Coroutine::create(function () {
|
||||||
|
if (version_compare('7.1.0', PHP_VERSION, '>')) {
|
||||||
|
fwrite(
|
||||||
|
STDERR,
|
||||||
|
sprintf(
|
||||||
|
'This version of PHPUnit is supported on PHP 7.1 and PHP 7.2.' . PHP_EOL .
|
||||||
|
'You are using PHP %s (%s).' . PHP_EOL,
|
||||||
|
PHP_VERSION,
|
||||||
|
PHP_BINARY
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ini_get('date.timezone')) {
|
||||||
|
ini_set('date.timezone', 'UTC');
|
||||||
|
}
|
||||||
|
|
||||||
|
$dirs = [
|
||||||
|
getcwd() . '/vendor/autoload.php',
|
||||||
|
__DIR__ . '/../../autoload.php',
|
||||||
|
__DIR__ . '/../vendor/autoload.php',
|
||||||
|
__DIR__ . '/vendor/autoload.php',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($dirs as $file) {
|
||||||
|
if (file_exists($file)) {
|
||||||
|
define('PHPUNIT_COMPOSER_INSTALL', $file);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($file);
|
||||||
|
|
||||||
|
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
|
||||||
|
fwrite(
|
||||||
|
STDERR,
|
||||||
|
'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL .
|
||||||
|
' composer install' . PHP_EOL . PHP_EOL .
|
||||||
|
'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL
|
||||||
|
);
|
||||||
|
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = getopt('', array('prepend:'));
|
||||||
|
|
||||||
|
if (isset($options['prepend'])) {
|
||||||
|
require $options['prepend'];
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($options);
|
||||||
|
|
||||||
|
require PHPUNIT_COMPOSER_INSTALL;
|
||||||
|
|
||||||
|
PHPUnit\TextUI\Command::main(false);
|
||||||
|
|
||||||
|
swoole_event_exit();
|
||||||
|
});
|
39
src/testing/composer.json
Normal file
39
src/testing/composer.json
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"name": "hyperf/testing",
|
||||||
|
"type": "library",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"php",
|
||||||
|
"swoole",
|
||||||
|
"testing"
|
||||||
|
],
|
||||||
|
"description": "Testing for hyperf",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Hyperf\\Testing\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2",
|
||||||
|
"phpunit/phpunit": "^7.0",
|
||||||
|
"hyperf/utils": "dev-master"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"malukenho/docheader": "^0.1.6",
|
||||||
|
"mockery/mockery": "^1.0",
|
||||||
|
"friendsofphp/php-cs-fixer": "^2.9"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"co-phpunit"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "./vendor/bin/phpunit -c phpunit.xml",
|
||||||
|
"co_test": "php tests/co_phpunit.php -c phpunit.xml"
|
||||||
|
}
|
||||||
|
}
|
200
src/testing/src/Client.php
Normal file
200
src/testing/src/Client.php
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
/**
|
||||||
|
* This file is part of Hyperf.
|
||||||
|
*
|
||||||
|
* @link https://www.hyperf.io
|
||||||
|
* @document https://doc.hyperf.io
|
||||||
|
* @contact group@hyperf.io
|
||||||
|
* @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Hyperf\Testing;
|
||||||
|
|
||||||
|
use Hyperf\Contract\PackerInterface;
|
||||||
|
use Hyperf\Dispatcher\HttpDispatcher;
|
||||||
|
use Hyperf\HttpMessage\Server\Request as Psr7Request;
|
||||||
|
use Hyperf\HttpMessage\Server\Response as Psr7Response;
|
||||||
|
use Hyperf\HttpMessage\Stream\SwooleStream;
|
||||||
|
use Hyperf\HttpMessage\Upload\UploadedFile;
|
||||||
|
use Hyperf\HttpMessage\Uri\Uri;
|
||||||
|
use Hyperf\HttpServer\CoreMiddleware;
|
||||||
|
use Hyperf\HttpServer\MiddlewareManager;
|
||||||
|
use Hyperf\HttpServer\Server;
|
||||||
|
use Hyperf\Utils\Arr;
|
||||||
|
use Hyperf\Utils\Context;
|
||||||
|
use Hyperf\Utils\Filesystem\Filesystem;
|
||||||
|
use Hyperf\Utils\Packer\JsonPacker;
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Swoole\Coroutine as SwCoroutine;
|
||||||
|
|
||||||
|
class Client extends Server
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var PackerInterface
|
||||||
|
*/
|
||||||
|
protected $packer;
|
||||||
|
|
||||||
|
public function __construct(ContainerInterface $container, PackerInterface $packer = null, $server = 'http')
|
||||||
|
{
|
||||||
|
parent::__construct('http', CoreMiddleware::class, $container, $container->get(HttpDispatcher::class));
|
||||||
|
$this->packer = $packer ?? new JsonPacker();
|
||||||
|
|
||||||
|
$this->initCoreMiddleware($server);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get($uri, $data = [], $headers = [])
|
||||||
|
{
|
||||||
|
$response = $this->request('GET', $uri, [
|
||||||
|
'headers' => $headers,
|
||||||
|
'query' => $data,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->packer->unpack($response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function post($uri, $data = [], $headers = [])
|
||||||
|
{
|
||||||
|
$response = $this->request('POST', $uri, [
|
||||||
|
'headers' => $headers,
|
||||||
|
'form_params' => $data,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->packer->unpack($response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function json($uri, $data = [], $headers = [])
|
||||||
|
{
|
||||||
|
$headers['Content-Type'] = 'application/json';
|
||||||
|
$response = $this->request('POST', $uri, [
|
||||||
|
'headers' => $headers,
|
||||||
|
'json' => $data,
|
||||||
|
]);
|
||||||
|
return $this->packer->unpack($response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function file($uri, $data = [], $headers = [])
|
||||||
|
{
|
||||||
|
$multipart = [];
|
||||||
|
if (Arr::isAssoc($data)) {
|
||||||
|
$data = [$data];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($data as $item) {
|
||||||
|
$name = $item['name'];
|
||||||
|
$file = $item['file'];
|
||||||
|
|
||||||
|
$multipart[] = [
|
||||||
|
'name' => $name,
|
||||||
|
'contents' => fopen($file, 'r'),
|
||||||
|
'filename' => basename($file),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $this->request('POST', $uri, [
|
||||||
|
'headers' => $headers,
|
||||||
|
'multipart' => $multipart,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->packer->unpack($response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function request(string $method, string $path, array $options = [])
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @var Psr7Request
|
||||||
|
*/
|
||||||
|
[$psr7Request, $psr7Response] = $this->init($method, $path, $options);
|
||||||
|
|
||||||
|
$middlewares = array_merge($this->middlewares, MiddlewareManager::get($this->serverName, $psr7Request->getUri()->getPath(), $psr7Request->getMethod()));
|
||||||
|
|
||||||
|
return $this->dispatcher->dispatch($psr7Request, $middlewares, $this->coreMiddleware);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init(string $method, string $path, array $options = []): array
|
||||||
|
{
|
||||||
|
$this->flushContext();
|
||||||
|
|
||||||
|
$query = $options['query'] ?? [];
|
||||||
|
$params = $options['form_params'] ?? [];
|
||||||
|
$json = $options['json'] ?? [];
|
||||||
|
$headers = $options['headers'] ?? [];
|
||||||
|
$multipart = $options['multipart'] ?? [];
|
||||||
|
|
||||||
|
$data = $params;
|
||||||
|
|
||||||
|
// Initialize PSR-7 Request and Response objects.
|
||||||
|
$uri = (new Uri())->withPath($path)->withQuery(http_build_query($query));
|
||||||
|
|
||||||
|
$content = http_build_query($params);
|
||||||
|
if ($method == 'POST' && data_get($headers, 'Content-Type') == 'application/json') {
|
||||||
|
$content = json_encode($json, JSON_UNESCAPED_UNICODE);
|
||||||
|
$data = $json;
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = new SwooleStream($content);
|
||||||
|
|
||||||
|
$request = new Psr7Request($method, $uri, $headers, $body);
|
||||||
|
$request = $request->withQueryParams($query)
|
||||||
|
->withParsedBody($data)
|
||||||
|
->withUploadedFiles($this->normalizeFiles($multipart));
|
||||||
|
|
||||||
|
Context::set(ServerRequestInterface::class, $psr7Request = $request);
|
||||||
|
Context::set(ResponseInterface::class, $psr7Response = new Psr7Response());
|
||||||
|
|
||||||
|
return [$psr7Request, $psr7Response];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function flushContext()
|
||||||
|
{
|
||||||
|
$context = SwCoroutine::getContext();
|
||||||
|
|
||||||
|
foreach ($context as $key => $value) {
|
||||||
|
unset($context[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function normalizeFiles(array $multipart): array
|
||||||
|
{
|
||||||
|
$files = [];
|
||||||
|
$fileSystem = $this->container->get(Filesystem::class);
|
||||||
|
|
||||||
|
foreach ($multipart as $item) {
|
||||||
|
if (isset($item['name'], $item['contents'], $item['filename'])) {
|
||||||
|
$name = $item['name'];
|
||||||
|
$contents = $item['contents'];
|
||||||
|
$filename = $item['filename'];
|
||||||
|
|
||||||
|
$dir = BASE_PATH . '/runtime/uploads';
|
||||||
|
$tmpName = $dir . '/' . $filename;
|
||||||
|
$fileSystem->makeDirectory($dir);
|
||||||
|
$fileSystem->put($tmpName, $contents);
|
||||||
|
|
||||||
|
$stats = fstat($contents);
|
||||||
|
|
||||||
|
$files[$name] = new UploadedFile(
|
||||||
|
$tmpName,
|
||||||
|
$stats['size'],
|
||||||
|
0,
|
||||||
|
$name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getStream(string $resource)
|
||||||
|
{
|
||||||
|
$stream = fopen('php://temp', 'r+');
|
||||||
|
if ($resource !== '') {
|
||||||
|
fwrite($stream, $resource);
|
||||||
|
fseek($stream, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $stream;
|
||||||
|
}
|
||||||
|
}
|
103
src/testing/src/HttpClient.php
Normal file
103
src/testing/src/HttpClient.php
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
/**
|
||||||
|
* This file is part of Hyperf.
|
||||||
|
*
|
||||||
|
* @link https://www.hyperf.io
|
||||||
|
* @document https://doc.hyperf.io
|
||||||
|
* @contact group@hyperf.io
|
||||||
|
* @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Hyperf\Testing;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use Hyperf\Contract\PackerInterface;
|
||||||
|
use Hyperf\Utils\Arr;
|
||||||
|
use Hyperf\Utils\Packer\JsonPacker;
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
|
class HttpClient
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ContainerInterface
|
||||||
|
*/
|
||||||
|
protected $container;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Client
|
||||||
|
*/
|
||||||
|
protected $client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PackerInterface
|
||||||
|
*/
|
||||||
|
protected $packer;
|
||||||
|
|
||||||
|
public function __construct(ContainerInterface $container, PackerInterface $packer = null, $baseUri = 'http://127.0.0.1:9501')
|
||||||
|
{
|
||||||
|
$this->container = $container;
|
||||||
|
$this->packer = $packer ?? new JsonPacker();
|
||||||
|
$this->client = new Client([
|
||||||
|
'base_uri' => $baseUri,
|
||||||
|
'timeout' => 2,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get($uri, $data = [], $headers = [])
|
||||||
|
{
|
||||||
|
$response = $this->client->get($uri, [
|
||||||
|
'headers' => $headers,
|
||||||
|
'query' => $data,
|
||||||
|
]);
|
||||||
|
return $this->packer->unpack($response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function post($uri, $data = [], $headers = [])
|
||||||
|
{
|
||||||
|
$response = $this->client->post($uri, [
|
||||||
|
'headers' => $headers,
|
||||||
|
'form_params' => $data,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->packer->unpack($response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function json($uri, $data = [], $headers = [])
|
||||||
|
{
|
||||||
|
$headers['Content-Type'] = 'application/json';
|
||||||
|
$response = $this->client->post($uri, [
|
||||||
|
'json' => $data,
|
||||||
|
'headers' => $headers,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->packer->unpack($response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function file($uri, $data = [], $headers = [])
|
||||||
|
{
|
||||||
|
$multipart = [];
|
||||||
|
if (Arr::isAssoc($data)) {
|
||||||
|
$data = [$data];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($data as $item) {
|
||||||
|
$name = $item['name'];
|
||||||
|
$file = $item['file'];
|
||||||
|
|
||||||
|
$multipart[] = [
|
||||||
|
'name' => $name,
|
||||||
|
'contents' => fopen($file, 'r'),
|
||||||
|
'filename' => basename($file),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $this->client->post($uri, [
|
||||||
|
'headers' => $headers,
|
||||||
|
'multipart' => $multipart,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->packer->unpack($response->getBody()->getContents());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user