Skip to content

Commit 966475b

Browse files
committed
Added testing component.
0 parents  commit 966475b

File tree

4 files changed

+405
-0
lines changed

4 files changed

+405
-0
lines changed

co-phpunit

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/usr/bin/env php
2+
<?php
3+
\Swoole\Coroutine::create(function () {
4+
if (version_compare('7.1.0', PHP_VERSION, '>')) {
5+
fwrite(
6+
STDERR,
7+
sprintf(
8+
'This version of PHPUnit is supported on PHP 7.1 and PHP 7.2.' . PHP_EOL .
9+
'You are using PHP %s (%s).' . PHP_EOL,
10+
PHP_VERSION,
11+
PHP_BINARY
12+
)
13+
);
14+
15+
die(1);
16+
}
17+
18+
if (!ini_get('date.timezone')) {
19+
ini_set('date.timezone', 'UTC');
20+
}
21+
22+
$dirs = [
23+
getcwd() . '/vendor/autoload.php',
24+
__DIR__ . '/../../autoload.php',
25+
__DIR__ . '/../vendor/autoload.php',
26+
__DIR__ . '/vendor/autoload.php',
27+
];
28+
29+
foreach ($dirs as $file) {
30+
if (file_exists($file)) {
31+
define('PHPUNIT_COMPOSER_INSTALL', $file);
32+
33+
break;
34+
}
35+
}
36+
37+
unset($file);
38+
39+
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
40+
fwrite(
41+
STDERR,
42+
'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL .
43+
' composer install' . PHP_EOL . PHP_EOL .
44+
'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL
45+
);
46+
47+
die(1);
48+
}
49+
50+
$options = getopt('', array('prepend:'));
51+
52+
if (isset($options['prepend'])) {
53+
require $options['prepend'];
54+
}
55+
56+
unset($options);
57+
58+
require PHPUNIT_COMPOSER_INSTALL;
59+
60+
PHPUnit\TextUI\Command::main(false);
61+
62+
swoole_event_exit();
63+
});

composer.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "hyperf/testing",
3+
"type": "library",
4+
"license": "MIT",
5+
"keywords": [
6+
"php",
7+
"swoole",
8+
"testing"
9+
],
10+
"description": "Testing for hyperf",
11+
"autoload": {
12+
"psr-4": {
13+
"Hyperf\\Testing\\": "src/"
14+
}
15+
},
16+
"autoload-dev": {
17+
"psr-4": {
18+
}
19+
},
20+
"require": {
21+
"php": ">=7.2",
22+
"phpunit/phpunit": "^7.0",
23+
"hyperf/utils": "dev-master"
24+
},
25+
"require-dev": {
26+
"malukenho/docheader": "^0.1.6",
27+
"mockery/mockery": "^1.0",
28+
"friendsofphp/php-cs-fixer": "^2.9"
29+
},
30+
"suggest": {
31+
},
32+
"bin": [
33+
"co-phpunit"
34+
],
35+
"scripts": {
36+
"test": "./vendor/bin/phpunit -c phpunit.xml",
37+
"co_test": "php tests/co_phpunit.php -c phpunit.xml"
38+
}
39+
}

src/Client.php

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of Hyperf.
6+
*
7+
* @link https://www.hyperf.io
8+
* @document https://doc.hyperf.io
9+
* @contact [email protected]
10+
* @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
11+
*/
12+
13+
namespace Hyperf\Testing;
14+
15+
use Hyperf\Contract\PackerInterface;
16+
use Hyperf\Dispatcher\HttpDispatcher;
17+
use Hyperf\HttpMessage\Server\Request as Psr7Request;
18+
use Hyperf\HttpMessage\Server\Response as Psr7Response;
19+
use Hyperf\HttpMessage\Stream\SwooleStream;
20+
use Hyperf\HttpMessage\Upload\UploadedFile;
21+
use Hyperf\HttpMessage\Uri\Uri;
22+
use Hyperf\HttpServer\CoreMiddleware;
23+
use Hyperf\HttpServer\MiddlewareManager;
24+
use Hyperf\HttpServer\Server;
25+
use Hyperf\Utils\Arr;
26+
use Hyperf\Utils\Context;
27+
use Hyperf\Utils\Filesystem\Filesystem;
28+
use Hyperf\Utils\Packer\JsonPacker;
29+
use Psr\Container\ContainerInterface;
30+
use Psr\Http\Message\ResponseInterface;
31+
use Psr\Http\Message\ServerRequestInterface;
32+
use Swoole\Coroutine as SwCoroutine;
33+
34+
class Client extends Server
35+
{
36+
/**
37+
* @var PackerInterface
38+
*/
39+
protected $packer;
40+
41+
public function __construct(ContainerInterface $container, PackerInterface $packer = null, $server = 'http')
42+
{
43+
parent::__construct('http', CoreMiddleware::class, $container, $container->get(HttpDispatcher::class));
44+
$this->packer = $packer ?? new JsonPacker();
45+
46+
$this->initCoreMiddleware($server);
47+
}
48+
49+
public function get($uri, $data = [], $headers = [])
50+
{
51+
$response = $this->request('GET', $uri, [
52+
'headers' => $headers,
53+
'query' => $data,
54+
]);
55+
56+
return $this->packer->unpack($response->getBody()->getContents());
57+
}
58+
59+
public function post($uri, $data = [], $headers = [])
60+
{
61+
$response = $this->request('POST', $uri, [
62+
'headers' => $headers,
63+
'form_params' => $data,
64+
]);
65+
66+
return $this->packer->unpack($response->getBody()->getContents());
67+
}
68+
69+
public function json($uri, $data = [], $headers = [])
70+
{
71+
$headers['Content-Type'] = 'application/json';
72+
$response = $this->request('POST', $uri, [
73+
'headers' => $headers,
74+
'json' => $data,
75+
]);
76+
return $this->packer->unpack($response->getBody()->getContents());
77+
}
78+
79+
public function file($uri, $data = [], $headers = [])
80+
{
81+
$multipart = [];
82+
if (Arr::isAssoc($data)) {
83+
$data = [$data];
84+
}
85+
86+
foreach ($data as $item) {
87+
$name = $item['name'];
88+
$file = $item['file'];
89+
90+
$multipart[] = [
91+
'name' => $name,
92+
'contents' => fopen($file, 'r'),
93+
'filename' => basename($file),
94+
];
95+
}
96+
97+
$response = $this->request('POST', $uri, [
98+
'headers' => $headers,
99+
'multipart' => $multipart,
100+
]);
101+
102+
return $this->packer->unpack($response->getBody()->getContents());
103+
}
104+
105+
public function request(string $method, string $path, array $options = [])
106+
{
107+
/*
108+
* @var Psr7Request
109+
*/
110+
[$psr7Request, $psr7Response] = $this->init($method, $path, $options);
111+
112+
$middlewares = array_merge($this->middlewares, MiddlewareManager::get($this->serverName, $psr7Request->getUri()->getPath(), $psr7Request->getMethod()));
113+
114+
return $this->dispatcher->dispatch($psr7Request, $middlewares, $this->coreMiddleware);
115+
}
116+
117+
protected function init(string $method, string $path, array $options = []): array
118+
{
119+
$this->flushContext();
120+
121+
$query = $options['query'] ?? [];
122+
$params = $options['form_params'] ?? [];
123+
$json = $options['json'] ?? [];
124+
$headers = $options['headers'] ?? [];
125+
$multipart = $options['multipart'] ?? [];
126+
127+
$data = $params;
128+
129+
// Initialize PSR-7 Request and Response objects.
130+
$uri = (new Uri())->withPath($path)->withQuery(http_build_query($query));
131+
132+
$content = http_build_query($params);
133+
if ($method == 'POST' && data_get($headers, 'Content-Type') == 'application/json') {
134+
$content = json_encode($json, JSON_UNESCAPED_UNICODE);
135+
$data = $json;
136+
}
137+
138+
$body = new SwooleStream($content);
139+
140+
$request = new Psr7Request($method, $uri, $headers, $body);
141+
$request = $request->withQueryParams($query)
142+
->withParsedBody($data)
143+
->withUploadedFiles($this->normalizeFiles($multipart));
144+
145+
Context::set(ServerRequestInterface::class, $psr7Request = $request);
146+
Context::set(ResponseInterface::class, $psr7Response = new Psr7Response());
147+
148+
return [$psr7Request, $psr7Response];
149+
}
150+
151+
protected function flushContext()
152+
{
153+
$context = SwCoroutine::getContext();
154+
155+
foreach ($context as $key => $value) {
156+
unset($context[$key]);
157+
}
158+
}
159+
160+
protected function normalizeFiles(array $multipart): array
161+
{
162+
$files = [];
163+
$fileSystem = $this->container->get(Filesystem::class);
164+
165+
foreach ($multipart as $item) {
166+
if (isset($item['name'], $item['contents'], $item['filename'])) {
167+
$name = $item['name'];
168+
$contents = $item['contents'];
169+
$filename = $item['filename'];
170+
171+
$dir = BASE_PATH . '/runtime/uploads';
172+
$tmpName = $dir . '/' . $filename;
173+
$fileSystem->makeDirectory($dir);
174+
$fileSystem->put($tmpName, $contents);
175+
176+
$stats = fstat($contents);
177+
178+
$files[$name] = new UploadedFile(
179+
$tmpName,
180+
$stats['size'],
181+
0,
182+
$name
183+
);
184+
}
185+
}
186+
187+
return $files;
188+
}
189+
190+
protected function getStream(string $resource)
191+
{
192+
$stream = fopen('php://temp', 'r+');
193+
if ($resource !== '') {
194+
fwrite($stream, $resource);
195+
fseek($stream, 0);
196+
}
197+
198+
return $stream;
199+
}
200+
}

0 commit comments

Comments
 (0)