mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-02 14:25:38 +08:00
add HttpEventListener test (#200)
This commit is contained in:
@@ -35,7 +35,7 @@
|
|||||||
"jangregor/phpstan-prophecy": "^1.0",
|
"jangregor/phpstan-prophecy": "^1.0",
|
||||||
"jetbrains/phpstorm-attributes": "^1.0",
|
"jetbrains/phpstorm-attributes": "^1.0",
|
||||||
"mikey179/vfsstream": "^1.6",
|
"mikey179/vfsstream": "^1.6",
|
||||||
"phpspec/prophecy": "1.x-dev",
|
"phpspec/prophecy-phpunit": "^2.0",
|
||||||
"phpstan/extension-installer": "^1.1",
|
"phpstan/extension-installer": "^1.1",
|
||||||
"phpstan/phpstan": "^1.1",
|
"phpstan/phpstan": "^1.1",
|
||||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ parameters:
|
|||||||
- '#Unsafe usage of new static#'
|
- '#Unsafe usage of new static#'
|
||||||
- '#Call to method initTableList\(\) of deprecated class ZM\\DB\\DB#'
|
- '#Call to method initTableList\(\) of deprecated class ZM\\DB\\DB#'
|
||||||
- '#class Fiber#'
|
- '#class Fiber#'
|
||||||
|
- # Ignore Prophesize deprecation bug: https://github.com/phpstan/phpstan-deprecation-rules/issues/76
|
||||||
|
message: '#^Call to deprecated method prophesize\(\) of class Tests\\TestCase#'
|
||||||
|
path: tests
|
||||||
dynamicConstantNames:
|
dynamicConstantNames:
|
||||||
- SWOOLE_VERSION
|
- SWOOLE_VERSION
|
||||||
- ZM_TEST_LOG_DEBUG
|
- ZM_TEST_LOG_DEBUG
|
||||||
|
|||||||
@@ -4,24 +4,12 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Tests;
|
namespace Tests;
|
||||||
|
|
||||||
use Prophecy\Prophet;
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
class TestCase extends \PHPUnit\Framework\TestCase
|
class TestCase extends \PHPUnit\Framework\TestCase
|
||||||
{
|
{
|
||||||
protected Prophet $prophet;
|
use ProphecyTrait;
|
||||||
|
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
$this->prophet = new Prophet();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function tearDown(): void
|
|
||||||
{
|
|
||||||
parent::tearDown();
|
|
||||||
$this->prophet->checkPredictions();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,11 @@ declare(strict_types=1);
|
|||||||
namespace Tests\Trait;
|
namespace Tests\Trait;
|
||||||
|
|
||||||
use Prophecy\Argument;
|
use Prophecy\Argument;
|
||||||
use Prophecy\Prophet;
|
|
||||||
use Psr\Log\AbstractLogger;
|
use Psr\Log\AbstractLogger;
|
||||||
use Psr\Log\LogLevel;
|
use Psr\Log\LogLevel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模拟 Logger 行为
|
* 模拟 Logger 行为
|
||||||
* @property Prophet $prophet
|
|
||||||
*/
|
*/
|
||||||
trait HasLogger
|
trait HasLogger
|
||||||
{
|
{
|
||||||
@@ -37,7 +35,7 @@ trait HasLogger
|
|||||||
|
|
||||||
private function startMockLogger(): void
|
private function startMockLogger(): void
|
||||||
{
|
{
|
||||||
$logger = $this->prophet->prophesize(AbstractLogger::class);
|
$logger = $this->prophesize(AbstractLogger::class);
|
||||||
$levels = [
|
$levels = [
|
||||||
LogLevel::EMERGENCY,
|
LogLevel::EMERGENCY,
|
||||||
LogLevel::ALERT,
|
LogLevel::ALERT,
|
||||||
@@ -50,9 +48,11 @@ trait HasLogger
|
|||||||
];
|
];
|
||||||
$log_it = fn (...$args) => $this->mockLog(...$args);
|
$log_it = fn (...$args) => $this->mockLog(...$args);
|
||||||
foreach ($levels as $level) {
|
foreach ($levels as $level) {
|
||||||
$logger->{$level}(Argument::type('string'), Argument::any())->will(fn ($args) => $log_it($level, ...$args));
|
$logger->{$level}(Argument::type('string'), Argument::any())
|
||||||
|
->will(fn ($args) => $log_it($level, ...$args));
|
||||||
}
|
}
|
||||||
$logger->log(Argument::in($levels), Argument::type('string'), Argument::any())->will(fn ($args) => $log_it(...$args));
|
$logger->log(Argument::in($levels), Argument::type('string'), Argument::any())
|
||||||
|
->will(fn ($args) => $log_it(...$args));
|
||||||
ob_logger_register($logger->reveal());
|
ob_logger_register($logger->reveal());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
112
tests/ZM/Event/Listener/HttpEventListenerTest.php
Normal file
112
tests/ZM/Event/Listener/HttpEventListenerTest.php
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Tests\ZM\Event\Listener;
|
||||||
|
|
||||||
|
use Choir\Http\ServerRequest;
|
||||||
|
use Prophecy\Argument;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Symfony\Component\Routing\Route;
|
||||||
|
use Tests\TestCase;
|
||||||
|
use Tests\Trait\HasVirtualFileSystem;
|
||||||
|
use ZM\Event\Listener\HttpEventListener;
|
||||||
|
use ZM\Utils\HttpUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class HttpEventListenerTest extends TestCase
|
||||||
|
{
|
||||||
|
use HasVirtualFileSystem;
|
||||||
|
|
||||||
|
public function fakeHandler(): ?string
|
||||||
|
{
|
||||||
|
return 'I am here to greet';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHandleNotAllowedRoute(): void
|
||||||
|
{
|
||||||
|
$this->addRoute($this->mockHandler(false), 'fakeHandler');
|
||||||
|
|
||||||
|
$event = $this->mockRequestEvent(new ServerRequest('DELETE', '/test/get'), true);
|
||||||
|
HttpEventListener::getInstance()->onRequest999($event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHandleNotFoundRoute(): void
|
||||||
|
{
|
||||||
|
$this->addRoute($this->mockHandler(false), 'fakeHandler');
|
||||||
|
|
||||||
|
$event = $this->mockRequestEvent(new ServerRequest('GET', '/test/not-found'), false);
|
||||||
|
HttpEventListener::getInstance()->onRequest999($event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHandleFoundRoute(): void
|
||||||
|
{
|
||||||
|
$this->addRoute('', [$this->mockHandler(true), 'fakeHandler']);
|
||||||
|
|
||||||
|
$event = $this->mockRequestEvent(new ServerRequest('GET', '/test/get'), true);
|
||||||
|
HttpEventListener::getInstance()->onRequest999($event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHandleFoundRouteWithException(): void
|
||||||
|
{
|
||||||
|
$this->addRoute('', [$this->mockHandler(true, fn () => null), 'fakeHandler']);
|
||||||
|
|
||||||
|
$event = $this->mockRequestEvent(new ServerRequest('GET', '/test/get'), true);
|
||||||
|
HttpEventListener::getInstance()->onRequest999($event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHandleStaticFile(): void
|
||||||
|
{
|
||||||
|
$this->setUpVfs('static', [
|
||||||
|
'test.txt' => 'Hello, world!',
|
||||||
|
]);
|
||||||
|
$event = $this->mockRequestEvent(new ServerRequest('GET', '/test.txt'), true);
|
||||||
|
|
||||||
|
$old_conf = config('global.file_server.document_root');
|
||||||
|
config(['global.file_server.document_root' => $this->vfs->url()]);
|
||||||
|
HttpEventListener::getInstance()->onRequest1($event);
|
||||||
|
config(['global.file_server.document_root' => $old_conf]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addRoute($class, $method): void
|
||||||
|
{
|
||||||
|
HttpUtil::getRouteCollection()->remove('test.get');
|
||||||
|
$route = new Route('/test/get', ['_class' => $class, '_method' => $method], methods: ['GET']);
|
||||||
|
HttpUtil::getRouteCollection()->add('test.get', $route);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function mockRequestEvent(ServerRequest $request, bool $should_have_response): \HttpRequestEvent
|
||||||
|
{
|
||||||
|
$event = $this->prophesize(\HttpRequestEvent::class);
|
||||||
|
$event->getRequest()->willReturn($request);
|
||||||
|
$event->getResponse()->willReturn(null);
|
||||||
|
if ($should_have_response) {
|
||||||
|
$event->withResponse(Argument::type(ResponseInterface::class))
|
||||||
|
->will(function ($args) use ($event) {
|
||||||
|
$event->getResponse()->willReturn($args[0]);
|
||||||
|
return $event->reveal();
|
||||||
|
})
|
||||||
|
->shouldBeCalledOnce();
|
||||||
|
} else {
|
||||||
|
$event->withResponse(Argument::type(ResponseInterface::class))->shouldNotBeCalled();
|
||||||
|
}
|
||||||
|
return $event->reveal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function mockHandler(bool $should_be_called, callable $callback = null): self
|
||||||
|
{
|
||||||
|
$handler = $this->prophesize(self::class);
|
||||||
|
if ($should_be_called) {
|
||||||
|
$handler->fakeHandler(
|
||||||
|
Argument::type('array'),
|
||||||
|
Argument::type(ServerRequest::class),
|
||||||
|
Argument::type(\HttpRequestEvent::class)
|
||||||
|
)->will(fn () => $callback ? $callback() : 'OK!')->shouldBeCalledOnce();
|
||||||
|
} else {
|
||||||
|
$handler->fakeHandler(Argument::cetera())->shouldNotBeCalled();
|
||||||
|
}
|
||||||
|
return $handler->reveal();
|
||||||
|
}
|
||||||
|
}
|
||||||
37
tests/ZM/Event/Listener/SignalListenerTest.php
Normal file
37
tests/ZM/Event/Listener/SignalListenerTest.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Tests\ZM\Event\Listener;
|
||||||
|
|
||||||
|
use Tests\TestCase;
|
||||||
|
use Tests\Trait\HasLogger;
|
||||||
|
use ZM\Event\Listener\SignalListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class SignalListenerTest extends TestCase
|
||||||
|
{
|
||||||
|
use HasLogger;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->startMockLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires extension pcntl
|
||||||
|
*/
|
||||||
|
public function testListenWorkerSignal(): void
|
||||||
|
{
|
||||||
|
$l = new SignalListener();
|
||||||
|
$l->signalWorker();
|
||||||
|
// 检查信号处理器是否被设置
|
||||||
|
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||||
|
$h = pcntl_signal_get_handler(SIGINT);
|
||||||
|
$this->assertIsCallable($h);
|
||||||
|
$this->assertEquals([$l, 'onWorkerInt'], $h);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -190,7 +190,7 @@ class ZMResultPrinter extends CliTestDoxPrinter
|
|||||||
$out = '';
|
$out = '';
|
||||||
|
|
||||||
if ($message) {
|
if ($message) {
|
||||||
$out .= $this->prefixLines($prefix['message'], strtolower($message) . PHP_EOL) . PHP_EOL;
|
$out .= $this->prefixLines($prefix['message'], $message . PHP_EOL) . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($diff) {
|
if ($diff) {
|
||||||
|
|||||||
Reference in New Issue
Block a user