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