应用

Testing Is Documentation

tests/Kernel/AppTest.php应用 - 图1

应用是整个系统非常核心的一部分,定义了应用的骨架。

Uses

  1. <?php
  2. use Leevel\Di\Container;
  3. use Leevel\Di\IContainer;
  4. use Leevel\Di\Provider;
  5. use Leevel\Filesystem\Helper;
  6. use Leevel\Http\Request;
  7. use Leevel\Kernel\App as Apps;
  8. use Leevel\Kernel\IApp;
  9. use Leevel\Option\IOption;

基本使用

  1. public function testBaseUse(): void
  2. {
  3. $appPath = __DIR__.'/app';
  4. $app = $this->createApp();
  5. $container = $app->container();
  6. $this->assertInstanceof(IContainer::class, $container);
  7. $this->assertInstanceof(Container::class, $container);
  8. $this->assertInstanceof(IApp::class, $app);
  9. $this->assertInstanceof(Apps::class, $app);
  10. $this->assertSame($appPath, $app->path());
  11. $this->assertSame($appPath.'/foobar', $app->path('foobar'));
  12. }

version 获取程序版本

  1. public function testVersion(): void
  2. {
  3. $app = $this->createApp();
  4. $this->assertSame(App::VERSION, $app->version());
  5. }

isConsole 是否为 PHP 运行模式命令行

  1. public function testIsConsole(): void
  2. {
  3. $app = $this->createApp();
  4. $this->assertTrue($app->isConsole());
  5. }

setPath 设置基础路径

  1. public function testSetPath(): void
  2. {
  3. $app = $this->createApp();
  4. $app->setPath(__DIR__.'/foo');
  5. $this->assertSame(__DIR__.'/foo', $app->path());
  6. }

appPath 获取应用路径

  1. public function testAppPath(): void
  2. {
  3. $appPath = __DIR__.'/app';
  4. $app = $this->createApp();
  5. $container = $app->container();
  6. $request = $this->createMock(Request::class);
  7. $container->singleton('request', function () use ($request) {
  8. return $request;
  9. });
  10. $container->instance('app_name', 'Blog');
  11. $this->assertEquals('Blog', $container->make('app_name'));
  12. $this->assertSame($appPath.'/application', $app->appPath());
  13. $this->assertSame($appPath.'/application', $app->appPath(false));
  14. $this->assertSame($appPath.'/application', $app->appPath(''));
  15. $this->assertSame($appPath.'/application/blog', $app->appPath(true));
  16. $this->assertSame($appPath.'/application/foo', $app->appPath('foo'));
  17. $this->assertSame($appPath.'/application/bar', $app->appPath('bar'));
  18. $this->assertSame($appPath.'/application/foo/bar', $app->appPath(false, 'foo/bar'));
  19. $this->assertSame($appPath.'/application/foo/bar', $app->appPath('', 'foo/bar'));
  20. $this->assertSame($appPath.'/application/blog/foo/bar', $app->appPath(true, 'foo/bar'));
  21. $this->assertSame($appPath.'/application/foo/foo/bar', $app->appPath('foo', 'foo/bar'));
  22. $this->assertSame($appPath.'/application/bar/foo/bar', $app->appPath('bar', 'foo/bar'));
  23. }

setAppPath 设置应用路径

  1. public function testSetAppPath(): void
  2. {
  3. $appPath = __DIR__.'/app';
  4. $app = $this->createApp();
  5. $container = $app->container();
  6. $request = $this->createMock(Request::class);
  7. $container->singleton('request', function () use ($request) {
  8. return $request;
  9. });
  10. $container->instance('app_name', 'Blog');
  11. $this->assertEquals('Blog', $container->make('app_name'));
  12. $this->assertSame($appPath.'/application/blog', $app->appPath(true));
  13. $app->setAppPath(__DIR__.'/app/foo');
  14. $this->assertSame($appPath.'/foo/blog', $app->appPath(true));
  15. }

themePath 获取应用主题目录

  1. public function testPathTheme(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/application/ui/theme', $app->themePath());
  6. $this->assertSame($appPath.'/application/blog/ui/theme', $app->themePath('blog'));
  7. }

commonPath 获取公共路径

  1. public function testCommonPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/common', $app->commonPath());
  6. $this->assertSame($appPath.'/common/foobar', $app->commonPath('foobar'));
  7. }

setCommonPath 设置公共路径

  1. public function testSetCommonPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/common', $app->commonPath());
  6. $this->assertSame($appPath.'/common/foobar', $app->commonPath('foobar'));
  7. $app->setCommonPath(__DIR__.'/app/commonFoo');
  8. $this->assertSame($appPath.'/commonFoo', $app->commonPath());
  9. $this->assertSame($appPath.'/commonFoo/foobar', $app->commonPath('foobar'));
  10. }

runtimePath 获取运行路径

  1. public function testRuntimePath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/runtime', $app->runtimePath());
  6. $this->assertSame($appPath.'/runtime/foobar', $app->runtimePath('foobar'));
  7. }

setRuntimePath 设置运行时路径

  1. public function testSetRuntimePath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/runtime', $app->runtimePath());
  6. $this->assertSame($appPath.'/runtime/foobar', $app->runtimePath('foobar'));
  7. $app->setRuntimePath(__DIR__.'/app/runtimeFoo');
  8. $this->assertSame($appPath.'/runtimeFoo', $app->runtimePath());
  9. $this->assertSame($appPath.'/runtimeFoo/foobar', $app->runtimePath('foobar'));
  10. }

version 获取附件存储路径

  1. public function testStoragePath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/storage', $app->storagePath());
  6. $this->assertSame($appPath.'/storage/foobar', $app->storagePath('foobar'));
  7. }

setStoragePath 设置附件存储路径

  1. public function testSetStoragePath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/storage', $app->storagePath());
  6. $this->assertSame($appPath.'/storage/foobar', $app->storagePath('foobar'));
  7. $app->setStoragePath(__DIR__.'/app/storageFoo');
  8. $this->assertSame($appPath.'/storageFoo', $app->storagePath());
  9. $this->assertSame($appPath.'/storageFoo/foobar', $app->storagePath('foobar'));
  10. }

optionPath 获取配置路径

  1. public function testOptionPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/option', $app->optionPath());
  6. $this->assertSame($appPath.'/option/foobar', $app->optionPath('foobar'));
  7. }

setOptionPath 设置配置路径

  1. public function testSetOptionPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/option', $app->optionPath());
  6. $this->assertSame($appPath.'/option/foobar', $app->optionPath('foobar'));
  7. $app->setOptionPath(__DIR__.'/app/optionFoo');
  8. $this->assertSame($appPath.'/optionFoo', $app->optionPath());
  9. $this->assertSame($appPath.'/optionFoo/foobar', $app->optionPath('foobar'));
  10. }

i18nPath 获取语言包路径

  1. public function testI18nPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/i18n', $app->i18nPath());
  6. $this->assertSame($appPath.'/i18n/foobar', $app->i18nPath('foobar'));
  7. }

setI18nPath 设置语言包路径

  1. public function testSetI18nPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/i18n', $app->i18nPath());
  6. $this->assertSame($appPath.'/i18n/foobar', $app->i18nPath('foobar'));
  7. $app->setI18nPath(__DIR__.'/app/i18nFoo');
  8. $this->assertSame($appPath.'/i18nFoo', $app->i18nPath());
  9. $this->assertSame($appPath.'/i18nFoo/foobar', $app->i18nPath('foobar'));
  10. }

envPath 获取环境变量路径

  1. public function testEnvPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath, $app->envPath());
  6. }

setEnvPath 设置环境变量路径

  1. public function testSetEnvPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath, $app->envPath());
  6. $app->setEnvPath(__DIR__.'/appFoo');
  7. $this->assertSame(__DIR__.'/appFoo', $app->envPath());
  8. }

envFile 获取环境变量文件

  1. public function testEnvFile(): void
  2. {
  3. $app = $this->createApp();
  4. $this->assertSame('.env', $app->envFile());
  5. }

setEnvFile 设置环境变量文件

  1. public function testSetEnvFile(): void
  2. {
  3. $app = $this->createApp();
  4. $this->assertSame('.env', $app->envFile());
  5. $app->setEnvFile('.envfoo');
  6. $this->assertSame('.envfoo', $app->envFile());
  7. }

fullEnvPath 获取环境变量完整路径

  1. public function testFullEnvPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/.env', $app->fullEnvPath());
  6. $app->setEnvPath(__DIR__.'/appFoo');
  7. $this->assertSame(__DIR__.'/appFoo/.env', $app->fullEnvPath());
  8. $app->setEnvFile('.envfoo');
  9. $this->assertSame(__DIR__.'/appFoo/.envfoo', $app->fullEnvPath());
  10. }

i18nCachedPath 获取语言包缓存路径

  1. public function testSetI18nCachePath(): void
  2. {
  3. $app = $this->createApp();
  4. $this->assertSame(__DIR__.'/app/bootstrap/i18n/zh-CN.php', $app->i18nCachedPath('zh-CN'));
  5. $app->setI18nCachedPath(__DIR__.'/hello');
  6. $this->assertSame(__DIR__.'/hello/zh-CN.php', $app->i18nCachedPath('zh-CN'));
  7. }

i18nCachedPath 获取语言包缓存路径

  1. public function testI18nCachedPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/bootstrap/i18n/zh-CN.php', $app->i18nCachedPath('zh-CN'));
  6. $this->assertSame($appPath.'/bootstrap/i18n/zh-TW.php', $app->i18nCachedPath('zh-TW'));
  7. $this->assertSame($appPath.'/bootstrap/i18n/en-US.php', $app->i18nCachedPath('en-US'));
  8. }

isCachedI18n 是否存在语言包缓存

  1. public function testIsCachedI18n(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertFalse($app->isCachedI18n('zh-CN'));
  6. mkdir($appPath.'/bootstrap/i18n', 0777, true);
  7. file_put_contents($appPath.'/bootstrap/i18n/zh-CN.php', 'foo');
  8. $this->assertTrue($app->isCachedI18n('zh-CN'));
  9. Helper::deleteDirectory($appPath);
  10. }

setOptionCachedPath 设置配置缓存路径

  1. public function testSetOptionCachePath(): void
  2. {
  3. $app = $this->createApp();
  4. $this->assertSame(__DIR__.'/app/bootstrap/option.php', $app->optionCachedPath());
  5. $app->setOptionCachedPath(__DIR__.'/hello');
  6. $this->assertSame(__DIR__.'/hello/option.php', $app->optionCachedPath());
  7. }

optionCachedPath 获取配置缓存路径

  1. public function testOptionCachedPath(): void
  2. {
  3. $app = $this->createApp();
  4. $appPath = __DIR__.'/app';
  5. $this->assertSame($appPath.'/bootstrap/option.php', $app->optionCachedPath());
  6. }

isCachedOption 是否存在配置缓存

  1. public function testIsCachedOption(): void
  2. {
  3. $appPath = __DIR__.'/app';
  4. $app = $this->createApp();
  5. $this->assertFalse($app->isCachedOption());
  6. mkdir($appPath.'/bootstrap', 0777, true);
  7. file_put_contents($optionPath = $appPath.'/bootstrap/option.php', 'foo');
  8. $this->assertTrue($app->isCachedOption());
  9. Helper::deleteDirectory($appPath);
  10. }

routerCachedPath 获取路由缓存路径

  1. public function testRouterCachedPath(): void
  2. {
  3. $appPath = __DIR__.'/app';
  4. $app = $this->createApp();
  5. $this->assertSame($appPath.'/bootstrap/router.php', $app->routerCachedPath());
  6. }

isCachedRouter 是否存在路由缓存

  1. public function testIsCachedRouter(): void
  2. {
  3. $appPath = __DIR__.'/app';
  4. $app = $this->createApp();
  5. $this->assertFalse($app->isCachedRouter());
  6. mkdir($appPath.'/bootstrap', 0777, true);
  7. file_put_contents($routerPath = $appPath.'/bootstrap/router.php', 'foo');
  8. $this->assertTrue($app->isCachedRouter());
  9. Helper::deleteDirectory($appPath);
  10. }

isDebug 是否开启调试

  1. public function testIsDebug(): void
  2. {
  3. $appPath = __DIR__.'/app';
  4. $app = $this->createApp();
  5. $container = $app->container();
  6. $option = $this->createMock(IOption::class);
  7. $option
  8. ->method('get')
  9. ->willReturnCallback(function (string $k) {
  10. $map = [
  11. 'debug' => true,
  12. 'environment' => 'development',
  13. ];
  14. return $map[$k];
  15. });
  16. $this->assertSame('development', $option->get('environment'));
  17. $this->assertTrue($option->get('debug'));
  18. $container->singleton('option', function () use ($option) {
  19. return $option;
  20. });
  21. $this->assertTrue($app->isDebug());
  22. }

isDevelopment 是否为开发环境

  1. public function testIsDevelopment(): void
  2. {
  3. $appPath = __DIR__.'/app';
  4. $app = $this->createApp();
  5. $container = $app->container();
  6. $option = $this->createMock(Request::class);
  7. $option->method('get')->willReturn('development');
  8. $this->assertEquals('development', $option->get('development'));
  9. $container->singleton('option', function () use ($option) {
  10. return $option;
  11. });
  12. $this->assertTrue($app->isDevelopment());
  13. }

environment 获取运行环境

  1. public function testEnvironment(): void
  2. {
  3. $appPath = __DIR__.'/app';
  4. $app = $this->createApp();
  5. $container = $app->container();
  6. $option = $this->createMock(Request::class);
  7. $option->method('get')->willReturn('foo');
  8. $this->assertEquals('foo', $option->get('development'));
  9. $container->singleton('option', function () use ($option) {
  10. return $option;
  11. });
  12. $this->assertSame('foo', $app->environment());
  13. }

bootstrap 初始化应用

fixture 定义

Tests\Kernel\BootstrapTest1

  1. namespace Tests\Kernel;
  2. class BootstrapTest1
  3. {
  4. public function handle()
  5. {
  6. $_SERVER['bootstrapTest1'] = 1;
  7. }
  8. }

Tests\Kernel\BootstrapTest2

  1. namespace Tests\Kernel;
  2. class BootstrapTest2
  3. {
  4. public function handle()
  5. {
  6. $_SERVER['bootstrapTest2'] = 1;
  7. }
  8. }

Tests\Console\Load1\Test1

  1. namespace Tests\Console\Load1;
  2. use Leevel\Console\Command;
  3. class Test1 extends Command
  4. {
  5. protected string $name = 'load1:test1';
  6. protected string $description = 'load1 test1 for command';
  7. public function handle(): int
  8. {
  9. $this->info('load1 test1');
  10. return 0;
  11. }
  12. }
  1. public function testBootstrap(): void
  2. {
  3. $app = $this->createApp();
  4. $app->bootstrap([BootstrapTest1::class, BootstrapTest2::class]);
  5. $this->assertSame(1, $_SERVER['bootstrapTest1']);
  6. $this->assertSame(1, $_SERVER['bootstrapTest2']);
  7. unset($_SERVER['bootstrapTest1'], $_SERVER['bootstrapTest2']);
  8. }

registerAppProviders 注册应用服务提供者

fixture 定义

Tests\Kernel\OptionTest

  1. namespace Tests\Kernel;
  2. class OptionTest
  3. {
  4. public function get(string $name)
  5. {
  6. if (':deferred_providers' === $name) {
  7. return [
  8. [
  9. 'foo' => 'Tests\\Kernel\\ProviderDeferTest1',
  10. ],
  11. [
  12. 'Tests\\Kernel\\ProviderDeferTest1' => [
  13. 'foo' => [
  14. 'Tests\\Kernel\\ProviderDeferTest1',
  15. ],
  16. ],
  17. ],
  18. ];
  19. }
  20. if (':composer.providers' === $name) {
  21. return [ProviderTest3::class];
  22. }
  23. }
  24. }

Tests\Kernel\ProviderTest3

  1. namespace Tests\Kernel;
  2. class ProviderTest3 extends Provider
  3. {
  4. public function __construct(IContainer $container)
  5. {
  6. }
  7. public function bootstrap()
  8. {
  9. $_SERVER['testRegisterProvidersBootstrap'] = 1;
  10. }
  11. public function register(): void
  12. {
  13. $_SERVER['testRegisterProvidersRegister'] = 1;
  14. }
  15. }

Tests\Kernel\ProviderDeferTest1

  1. namespace Tests\Kernel;
  2. class ProviderDeferTest1 extends Provider
  3. {
  4. public function register(): void
  5. {
  6. $_SERVER['providerDeferTest1'] = 1;
  7. $this->container->singleton('foo', function (IContainer $container) {
  8. return 'bar';
  9. });
  10. }
  11. public static function providers(): array
  12. {
  13. return [
  14. 'foo' => [
  15. 'Tests\\Kernel\\ProviderDeferTest1',
  16. ],
  17. ];
  18. }
  19. public static function isDeferred(): bool
  20. {
  21. return true;
  22. }
  23. }
  1. public function testRegisterProviders(): void
  2. {
  3. $app = $this->createApp();
  4. $container = $app->container();
  5. $option = new OptionTest();
  6. $container->singleton('option', function () use ($option) {
  7. return $option;
  8. });
  9. $app->registerAppProviders();
  10. // for deferredAlias
  11. $this->assertArrayNotHasKey('providerDeferTest1', $_SERVER);
  12. $this->assertSame('bar', $container->make('foo'));
  13. $this->assertSame('bar', $container->make(ProviderDeferTest1::class));
  14. $this->assertSame(1, $_SERVER['providerDeferTest1']);
  15. // for providers
  16. $this->assertSame(1, $_SERVER['testRegisterProvidersRegister']);
  17. $this->assertArrayHasKey('testRegisterProvidersBootstrap', $_SERVER);
  18. unset(
  19. $_SERVER['providerDeferTest1'],
  20. $_SERVER['testRegisterProvidersRegister']
  21. );
  22. // bootstrap
  23. $this->assertTrue($container->isBootstrap());
  24. $this->assertSame(1, $_SERVER['testRegisterProvidersBootstrap']);
  25. unset($_SERVER['testRegisterProvidersBootstrap']);
  26. $this->assertTrue($container->isBootstrap());
  27. // again but already bootstrap
  28. $app->registerAppProviders();
  29. $this->assertArrayNotHasKey('testRegisterProvidersBootstrap', $_SERVER);
  30. $this->assertArrayNotHasKey('testRegisterProvidersRegister', $_SERVER);
  31. }

setPublicPath 设置资源路径

  1. public function testSetPublicPath(): void
  2. {
  3. $app = $this->createApp();
  4. $this->assertSame(__DIR__.'/app/public', $app->publicPath());
  5. $app->setPublicPath(__DIR__.'/hello');
  6. $this->assertSame(__DIR__.'/hello', $app->publicPath());
  7. }

setThemesPath 设置主题路径

  1. public function testSetThemesPath(): void
  2. {
  3. $app = $this->createApp();
  4. $this->assertSame(__DIR__.'/app/themes', $app->themesPath());
  5. $app->setThemesPath(__DIR__.'/hello');
  6. $this->assertSame(__DIR__.'/hello', $app->themesPath());
  7. }

env 获取应用的环境变量

测试数据

  1. # Tests\Kernel\AppTest::envProvider
  2. public function envProvider(): array
  3. {
  4. return [
  5. ['bar', 'true', true],
  6. ['bar', '(true)', true],
  7. ['bar', 'false', false],
  8. ['bar', '(false)', false],
  9. ['bar', 'empty', ''],
  10. ['bar', '(empty)', ''],
  11. ['bar', 'null', null],
  12. ['bar', '(null)', null],
  13. ['bar', '"hello"', 'hello'],
  14. ['bar', "'hello'", "'hello'"],
  15. ['bar', true, '1'],
  16. ['bar', false, ''],
  17. ['bar', 1, '1'],
  18. ['bar', '', ''],
  19. ];
  20. }
  1. public function testEnv(string $name, $value, $envValue): void
  2. {
  3. $app = $this->createApp();
  4. $name = 'test_env_'.$name;
  5. putenv($name.'='.$value);
  6. $this->assertSame($envValue, $app->env($name));
  7. }