应用
Testing Is Documentation
应用是整个系统非常核心的一部分,定义了应用的骨架。
Uses
php
<?php
use Leevel\Config\IConfig;
use Leevel\Di\Container;
use Leevel\Di\IContainer;
use Leevel\Di\Provider;
use Leevel\Filesystem\Helper;
use Leevel\Http\Request;
use Leevel\Kernel\App as Apps;
use Leevel\Kernel\IApp;
use Leevel\Kernel\Utils\Api;
use PHPUnit\Framework\Attributes\DataProvider;
基本使用
php
public function testBaseUse(): void
{
$appPath = __DIR__.'/app';
$app = $this->createApp();
$container = $app->container();
$this->assertInstanceof(IContainer::class, $container);
$this->assertInstanceof(Container::class, $container);
$this->assertInstanceof(IApp::class, $app);
$this->assertInstanceof(Apps::class, $app);
self::assertSame($appPath, $app->path());
self::assertSame($appPath.'/foobar', $app->path('foobar'));
}
version 获取程序版本
php
public function testVersion(): void
{
$app = $this->createApp();
self::assertSame(App::VERSION, $app->version());
}
isConsole 是否为 PHP 运行模式命令行
php
public function testIsConsole(): void
{
$app = $this->createApp();
self::assertTrue($app->isConsole());
}
setPath 设置基础路径
php
public function testSetPath(): void
{
$app = $this->createApp();
$app->setPath(__DIR__.'/foo');
self::assertSame(__DIR__.'/foo', $app->path());
}
appPath 获取应用路径
php
public function testAppPath(): void
{
$appPath = __DIR__.'/app';
$app = $this->createApp();
$container = $app->container();
$request = $this->createMock(Request::class);
$container->singleton('request', static function () use ($request) {
return $request;
});
self::assertSame($appPath, $app->appPath());
self::assertSame($appPath, $app->appPath(''));
self::assertSame($appPath.'/foo', $app->appPath('foo'));
self::assertSame($appPath.'/bar', $app->appPath('bar'));
self::assertSame($appPath.'/foo/foo/bar', $app->appPath('foo/foo/bar'));
self::assertSame($appPath.'/bar/foo/bar', $app->appPath('bar/foo/bar'));
}
setAppPath 设置应用路径
php
public function testSetAppPath(): void
{
$appPath = __DIR__.'/app';
$app = $this->createApp();
$container = $app->container();
$request = $this->createMock(Request::class);
$container->singleton('request', static function () use ($request) {
return $request;
});
self::assertSame($appPath, $app->appPath());
$app->setAppPath(__DIR__.'/app/foo');
self::assertSame($appPath.'/foo', $app->appPath());
}
storagePath 获取运行路径
php
public function testStoragePath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath.'/storage', $app->storagePath());
self::assertSame($appPath.'/storage/foobar', $app->storagePath('foobar'));
}
setStoragePath 设置运行时路径
php
public function testSetStoragePath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath.'/storage', $app->storagePath());
self::assertSame($appPath.'/storage/foobar', $app->storagePath('foobar'));
$app->setStoragePath(__DIR__.'/app/storageFoo');
self::assertSame($appPath.'/storageFoo', $app->storagePath());
self::assertSame($appPath.'/storageFoo/foobar', $app->storagePath('foobar'));
}
configPath 获取配置路径
php
public function testConfigPath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath.'/config', $app->configPath());
self::assertSame($appPath.'/config/foobar', $app->configPath('foobar'));
}
setConfigPath 设置配置路径
php
public function testSetConfigPath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath.'/config', $app->configPath());
self::assertSame($appPath.'/config/foobar', $app->configPath('foobar'));
$app->setConfigPath(__DIR__.'/app/configFoo');
self::assertSame($appPath.'/configFoo', $app->configPath());
self::assertSame($appPath.'/configFoo/foobar', $app->configPath('foobar'));
}
i18nPath 获取语言包路径
php
public function testI18nPath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath.'/i18n', $app->i18nPath());
self::assertSame($appPath.'/i18n/foobar', $app->i18nPath('foobar'));
}
setI18nPath 设置语言包路径
php
public function testSetI18nPath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath.'/i18n', $app->i18nPath());
self::assertSame($appPath.'/i18n/foobar', $app->i18nPath('foobar'));
$app->setI18nPath(__DIR__.'/app/i18nFoo');
self::assertSame($appPath.'/i18nFoo', $app->i18nPath());
self::assertSame($appPath.'/i18nFoo/foobar', $app->i18nPath('foobar'));
}
envPath 获取环境变量路径
php
public function testEnvPath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath, $app->envPath());
}
setEnvPath 设置环境变量路径
php
public function testSetEnvPath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath, $app->envPath());
$app->setEnvPath(__DIR__.'/appFoo');
self::assertSame(__DIR__.'/appFoo', $app->envPath());
}
envFile 获取环境变量文件
php
public function testEnvFile(): void
{
$app = $this->createApp();
self::assertSame('.env', $app->envFile());
}
setEnvFile 设置环境变量文件
php
public function testSetEnvFile(): void
{
$app = $this->createApp();
self::assertSame('.env', $app->envFile());
$app->setEnvFile('.envfoo');
self::assertSame('.envfoo', $app->envFile());
}
fullEnvPath 获取环境变量完整路径
php
public function testFullEnvPath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath.'/.env', $app->fullEnvPath());
$app->setEnvPath(__DIR__.'/appFoo');
self::assertSame(__DIR__.'/appFoo/.env', $app->fullEnvPath());
$app->setEnvFile('.envfoo');
self::assertSame(__DIR__.'/appFoo/.envfoo', $app->fullEnvPath());
}
i18nCachedPath 获取语言包缓存路径
php
public function testSetI18nCachePath(): void
{
$app = $this->createApp();
self::assertSame(__DIR__.'/app/storage/bootstrap/i18n/zh-CN.php', $app->i18nCachedPath('zh-CN'));
$app->setI18nCachedPath(__DIR__.'/hello');
self::assertSame(__DIR__.'/hello/zh-CN.php', $app->i18nCachedPath('zh-CN'));
}
i18nCachedPath 获取语言包缓存路径
php
public function testI18nCachedPath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath.'/storage/bootstrap/i18n/zh-CN.php', $app->i18nCachedPath('zh-CN'));
self::assertSame($appPath.'/storage/bootstrap/i18n/zh-TW.php', $app->i18nCachedPath('zh-TW'));
self::assertSame($appPath.'/storage/bootstrap/i18n/en-US.php', $app->i18nCachedPath('en-US'));
}
isCachedI18n 是否存在语言包缓存
php
public function testIsCachedI18n(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertFalse($app->isCachedI18n('zh-CN'));
mkdir($appPath.'/storage/bootstrap/i18n', 0o777, true);
file_put_contents($appPath.'/storage/bootstrap/i18n/zh-CN.php', 'foo');
self::assertTrue($app->isCachedI18n('zh-CN'));
Helper::deleteDirectory($appPath);
}
setConfigCachedPath 设置配置缓存路径
php
public function testSetConfigCachePath(): void
{
$app = $this->createApp();
self::assertSame(__DIR__.'/app/storage/bootstrap/config.php', $app->configCachedPath());
$app->setConfigCachedPath(__DIR__.'/hello');
self::assertSame(__DIR__.'/hello/config.php', $app->configCachedPath());
}
configCachedPath 获取配置缓存路径
php
public function testConfigCachedPath(): void
{
$app = $this->createApp();
$appPath = __DIR__.'/app';
self::assertSame($appPath.'/storage/bootstrap/config.php', $app->configCachedPath());
}
isCachedConfig 是否存在配置缓存
php
public function testIsCachedConfig(): void
{
$appPath = __DIR__.'/app';
$app = $this->createApp();
self::assertFalse($app->isCachedConfig());
mkdir($appPath.'/storage/bootstrap', 0o777, true);
file_put_contents($appPath.'/storage/bootstrap/config.php', 'foo');
self::assertTrue($app->isCachedConfig());
Helper::deleteDirectory($appPath);
}
routerCachedPath 获取路由缓存路径
php
public function testRouterCachedPath(): void
{
$appPath = __DIR__.'/app';
$app = $this->createApp();
self::assertSame($appPath.'/storage/bootstrap/router.php', $app->routerCachedPath());
}
isCachedRouter 是否存在路由缓存
php
public function testIsCachedRouter(): void
{
$appPath = __DIR__.'/app';
$app = $this->createApp();
self::assertFalse($app->isCachedRouter());
mkdir($appPath.'/storage/bootstrap', 0o777, true);
file_put_contents($routerPath = $appPath.'/storage/bootstrap/router.php', 'foo');
self::assertTrue($app->isCachedRouter());
Helper::deleteDirectory($appPath);
}
namespacePath 获取命名空间目录真实路径
php
public function testNamespacePath(): void
{
$appPath = \dirname(__DIR__, 2);
$app = $this->createApp($appPath);
self::assertSame(
\dirname(__DIR__, 2).'/src/Leevel/Kernel/Console',
realpath($app->namespacePath('Leevel\\Kernel\\Console'))
);
}
isDebug 是否开启调试
php
public function testIsDebug(): void
{
$app = $this->createApp();
$container = $app->container();
$config = $this->createMock(IConfig::class);
$config
->method('get')
->willReturnCallback(static function (string $k) {
$map = [
'debug' => true,
'environment' => 'development',
];
return $map[$k];
})
;
self::assertSame('development', $config->get('environment'));
self::assertTrue($config->get('debug'));
$container->singleton('config', static function () use ($config) {
return $config;
});
self::assertTrue($app->isDebug());
}
isDevelopment 是否为开发环境
php
public function testIsDevelopment(): void
{
$app = $this->createApp();
$container = $app->container();
$config = $this->createMock(Request::class);
$config->method('get')->willReturn('development');
self::assertSame('development', $config->get('development'));
$container->singleton('config', static function () use ($config) {
return $config;
});
self::assertTrue($app->isDevelopment());
}
environment 获取运行环境
php
public function testEnvironment(): void
{
$app = $this->createApp();
$container = $app->container();
$config = $this->createMock(Request::class);
$config->method('get')->willReturn('foo');
self::assertSame('foo', $config->get('development'));
$container->singleton('config', static function () use ($config) {
return $config;
});
self::assertSame('foo', $app->environment());
}
bootstrap 初始化应用
fixture 定义
Tests\Kernel\BootstrapTest1
php
namespace Tests\Kernel;
class BootstrapTest1
{
public function handle(): void
{
$_SERVER['bootstrapTest1'] = 1;
}
}
Tests\Kernel\BootstrapTest2
php
namespace Tests\Kernel;
class BootstrapTest2
{
public function handle(): void
{
$_SERVER['bootstrapTest2'] = 1;
}
}
Tests\Console\Load1\Test1
php
namespace Tests\Console\Load1;
use Leevel\Console\Command;
class Test1 extends Command
{
protected string $name = 'load1:test1';
protected string $description = 'load1 test1 for command';
public function handle(): int
{
$this->info('load1 test1');
return 0;
}
}
php
public function testBootstrap(): void
{
$app = $this->createApp();
$app->bootstrap([BootstrapTest1::class, BootstrapTest2::class]);
self::assertSame(1, $_SERVER['bootstrapTest1']);
self::assertSame(1, $_SERVER['bootstrapTest2']);
unset($_SERVER['bootstrapTest1'], $_SERVER['bootstrapTest2']);
}
registerAppProviders 注册应用服务提供者
fixture 定义
Tests\Kernel\ConfigTest
php
namespace Tests\Kernel;
class ConfigTest
{
public function get(string $name)
{
if (':deferred_providers' === $name) {
return [
[
'foo' => 'Tests\\Kernel\\ProviderDeferTest1',
],
[
'Tests\\Kernel\\ProviderDeferTest1' => [
'foo' => [
'Tests\\Kernel\\ProviderDeferTest1',
],
],
],
];
}
if (':composer.providers' === $name) {
return [ProviderTest3::class];
}
}
}
Tests\Kernel\ProviderTest3
php
namespace Tests\Kernel;
class ProviderTest3 extends Provider
{
public function __construct(IContainer $container) {}
public function bootstrap(): void
{
$_SERVER['testRegisterProvidersBootstrap'] = 1;
}
public function register(): void
{
$_SERVER['testRegisterProvidersRegister'] = 1;
}
}
Tests\Kernel\ProviderDeferTest1
php
namespace Tests\Kernel;
class ProviderDeferTest1 extends Provider
{
public function register(): void
{
$_SERVER['providerDeferTest1'] = 1;
$this->container->singleton('foo', static function (IContainer $container) {
return 'bar';
});
}
public static function providers(): array
{
return [
'foo' => [
'Tests\\Kernel\\ProviderDeferTest1',
],
];
}
public static function isDeferred(): bool
{
return true;
}
}
php
public function testRegisterProviders(): void
{
$app = $this->createApp();
$container = $app->container();
$config = new ConfigTest();
$container->singleton('config', static function () use ($config) {
return $config;
});
$app->registerAppProviders();
// for deferredAlias
self::assertArrayNotHasKey('providerDeferTest1', $_SERVER);
self::assertSame('bar', $container->make('foo'));
self::assertSame('bar', $container->make(ProviderDeferTest1::class));
self::assertSame(1, $_SERVER['providerDeferTest1']);
// for providers
self::assertSame(1, $_SERVER['testRegisterProvidersRegister']);
self::assertArrayHasKey('testRegisterProvidersBootstrap', $_SERVER);
unset(
$_SERVER['providerDeferTest1'],
$_SERVER['testRegisterProvidersRegister']
);
// bootstrap
self::assertTrue($container->isBootstrap());
self::assertSame(1, $_SERVER['testRegisterProvidersBootstrap']);
unset($_SERVER['testRegisterProvidersBootstrap']);
self::assertTrue($container->isBootstrap());
// again but already bootstrap
$app->registerAppProviders();
self::assertArrayNotHasKey('testRegisterProvidersBootstrap', $_SERVER);
self::assertArrayNotHasKey('testRegisterProvidersRegister', $_SERVER);
}
setThemesPath 设置主题路径
php
public function testSetThemesPath(): void
{
$app = $this->createApp();
self::assertSame(__DIR__.'/app/themes', $app->themesPath());
$app->setThemesPath(__DIR__.'/hello');
self::assertSame(__DIR__.'/hello', $app->themesPath());
}
env 获取应用的环境变量
测试数据
php
# Tests\Kernel\AppTest::envProvider
public static function envProvider(): array
{
return [
['bar', 'true', true],
['bar', '(true)', true],
['bar', 'false', false],
['bar', '(false)', false],
['bar', 'empty', ''],
['bar', '(empty)', ''],
['bar', 'null', null],
['bar', '(null)', null],
['bar', '"hello"', 'hello'],
['bar', "'hello'", "'hello'"],
['bar', true, '1'],
['bar', false, ''],
['bar', 1, '1'],
['bar', '', ''],
];
}
php
public function testEnv(string $name, $value, $envValue): void
{
$app = $this->createApp();
$name = 'test_env_'.$name;
putenv($name.'='.$value);
self::assertSame($envValue, $app->env($name));
}