内部的
composer require --dev proklung/phpunit-testing-tools
Создать класс:
使用 ProklTestingToolsBaseBaseTestCase;使用 ProklTestingToolsToolsContainerBuildContainer;类 ContainerAwareBaseTestCase 扩展 BaseTestCase {/** * @inheritDoc * @throws Exception */受保护的函数 setUp(): void{$this->container = static::$testContainer = BuildContainer::getTestContainer( ['dev/test_container.yaml','dev/local.yaml'],'/Resources/config', [new SampleCompilerPass()], // Опциональный параметр - кастомные 编译器通行证,'dev', // Окружение. По умолчанию - devtrue // 调试。 По умолчанию - true,['service_to_mock'] // Сервисы, подлежащие мокингу (см. подраздел Моки сервисов));parent::setUp(); } }
Отнаследовать от него тест。
Подгрузятся конфиги сервисов из указанных файлов по указанному пути (относительно DOCUMENT_ROOT тестов)。
Механизм(на базе создания прокси-сервисов по заданному списку)взят из бандла и адаптирован под локальные нужды。
使用 ProklTestingToolsToolsServiceMocker;使用 ProklTestingToolsBaseBaseTestCase;类 MyTest 扩展 BaseTestCase {使用 RestoreServiceContainer;受保护的函数 setUp(): void{parent::setUp(); $this->container = BuildContainer::getTestContainer( ['test_container.yaml'],'/../../../../tests/Standalone/Resource/config', [],'dev',true, ['filesystem.local.adapter'] // Сервис, который будет заменен моком.); } 公共函数 testFoo() {// 对于所有调用 ServiceMock::all($this->container->get('filesystem.local.adapter'), 'getAdapter', function () { return new Local( $_SERVER['DOCUMENT_ROOT'] . ' /测试/'); }); $result = $this->container->get('filesystem.local.adapter');// 仅用于下一次调用 ServiceMock::next($this->container->get('filesystem.local.adapter') , 'getAdapter', function () { return new Local( $_SERVER['DOCUMENT_ROOT'] . '/test/'); }); // 这会将一个新的可调用 ServiceMock::next($this->container->get('filesystem.local.adapter'), 'getAdapter', function () { throw new InvalidArgument('getAdapter 可以调用一次! '); });$mock = // 创建一个 PHPUnit 模拟或任何其他你想要的模拟。ServiceMocker::swap($this->container->get('filesystem.local.adapter'), $mock);// .. 。 $service = $this->container->get('filesystem.local.adapter'); $结果 = $service->getAdapter(); // Метод сервиса (или сервис целиком) подменен. }protected function teaDown(): void{// 确保我们不会影响其他测试ServiceMock::resetAll();// 您可以包含 RestoreServiceContainer 特征来自动重置服务} }
使用 ProklTestingToolsTraitsBootTestKernelTrait;class ExampleTest 扩展 ProklTestingToolsBaseBaseTestCase {使用 BootTestKernelTrait;受保护的函数 setUp(): void{parent::setUp();$container = new ContainerBuilder(); // ... Наполнение тестового контейнера.self::$kernel = $this->bootTestKernel($container); } }
Базовый класс для тестирования консольных команд。
回复:
executeCommand(Command $commandInstance, string $commandName, array $params = [])
- 执行命令,执行命令。
runCommand(Command $command, $input = [])
- execute
命令。
Несколько общих дата-провайдеров
provideEmptyValue
- пустые значения。
provideEmptyScalarValue
- пустые скалярные значения
provideBooleanValue
- булевы значения
provideDateTimeInstance
- 日期时间
provideNotExistingFilePath
- путь к несуществующему файлу
Обертка над。
示例(来自BaseTestCase
的 унаследованном от):
// Замокается полностью (т.е. не важно с какими параметрами пройдет вызов) функция in_the_loop $this->mockerFunctions->setNamespace('TestsAPI') ->full('in_the_loop', true) -> 模拟();
Namespace
- пространство имен, в котором мокается функция。
Или частичное моканье (в зависимости от аргументов):
// 获取 get_cat_name с аргументом $this->idCategory вернет 模拟类别 $this->mockerFunctions->setNamespace('TestAPIEntity') ->partial('get_cat_name', '模拟类别', $this->idCategory) ->partial('category_description', '模拟类别描述', $this->idCategory) -> 模拟();
При использовании этой фичи рекомендуется (во избежании проблем) на тест ставить аннотации:
/** * data() * * @runInSeparateProcess * @preserveGlobalState 禁用 */
Конструктор сервис-локаторов Symfony для тестов。
回复:
constructServiceLocator(array $config)
- 生成$config
示例:
$object = new ClassName();$config = [ 'service_key' => ClassName::class, 'service_key2' => $object, ];
Если передать название класса в конфиге,то внутри метода класс будет инстанцирован。
Форк пакета
使用 AppCommandCreateUserCommand;使用 ProklTestingToolsBaseBaseTestCase;使用 ProklTestingToolsToolsConsoleInteractsWithConsole;使用 ProklTestingToolsTraitsBootTestKernelTrait;类 CreateUserCommandTest 扩展 BaseTestCase {使用 InteractsWithConsole;使用 BootTestKernelTrait; 受保护函数 setUp(): void{parent::setUp();$container = new ContainerBuilder();$container->setDefinition( IntegrityCheck::class,新定义(IntegrityCheck::class,[]) )->setTags(['console.command' => ['command' => 'module:еуые']])->setPublic(true);self::$kernel = $this->bootTestKernel($container); $this->cliApplication = 新SymfonyBundleFrameworkBundleConsoleApplication(self::$kernel);$this->cliApplication->add($container->get(IntegrityCheck::class)); } 公共函数 test_can_create_user(): void{$this->executeConsoleCommand('create:user kbond --admin --role=ROLE_EMPLOYEE --role=ROLE_MANAGER') ->assertSuccessful() // 命令退出代码为 0->assertOutputContains('Creating admin user "kbond"') ->assertOutputContains('角色:ROLE_EMPLOYEE, ROLE_MANAGER') ->assertOutputNotContains('普通用户') ;// 高级用法$this->consoleCommand(CreateUserCommand::class) // 可以使用命令类或“name”->splitOutputStreams() // 默认情况下stdout/stderr是组合的,这个选项将它们分开->addArgument( 'kbond') ->addOption('--admin') // 带或不带“--”前缀->addOption('role', ['ROLE_EMPLOYEE', 'ROLE_MANAGER']) ->addOption('-R') // 快捷方式选项需要“-”前缀->addOption('-vv') // 默认情况下,输出具有正常的详细程度,使用标准选项更改 (-q, -v , -vv, -vvv)->addOption('--ansi') // 默认情况下,输出是未修饰的,使用此选项进行修饰->execute() // 运行命令->assertSuccessful() ->assertStatusCode(0) // 相当于 ->assertSuccessful()->assertOutputContains('Creating admin user "kbond"') ->assertErrorOutputContains('this is in stderr') // 与 ->splitOutputStreams()->assertErrorOutputNotContains('admin user') 结合使用 ->splitOutputStreams()->dump() // 转储() 状态代码/输出和 continue->dd() // dd() 状态代码/输出;// 测试交互命令$this->executeConsoleCommand('create:user', ['kbond']) ->断言成功() ->assertOutputContains('创建普通用户“kbond”') ; // 高级测试交互命令$this->consoleCommand(CreateUserCommand::class) ->addInput('kbond') ->addOption('--no-interaction') // 如果提供了输入,命令将以交互方式运行,使用此选项禁用->execute() ->断言成功() ->assertOutputContains('创建普通用户“kbond”') ; // 访问结果$result = $this->executeConsoleCommand('create:user');$result->statusCode();$result->output(); $结果->错误输出(); } }
Или:
使用 AppCommandCreateUserCommand;使用 PHPUnitFrameworkTestCase;使用 ProklTestingToolsToolsConsoleTestCommand;类 CreateUserCommandTest 扩展 TestCase {公共函数test_can_create_user(): void{ TestCommand::for(new CreateUserCommand(/** args... */)) ->splitOutputStreams() // 默认情况下 stdout/stderr 是组合的,此选项将它们分开->addArgument('kbond') ->addOption('--admin') // 带或不带“--”前缀->addOption('role', ['ROLE_EMPLOYEE', 'ROLE_MANAGER']) ->addOption('-R') // 快捷方式选项需要“-”前缀->addOption('-vv') // 默认情况下,输出具有正常的详细程度,使用标准选项更改 (-q, -v , -vv, -vvv)->addOption('--ansi') // 默认情况下,输出是未修饰的,使用此选项来修饰->execute() ->断言成功() ->assertStatusCode(0) // 相当于 ->assertSuccessful()->assertOutputContains('Creating admin user "kbond"') ->assertErrorOutputContains('this is in stderr') // 与 ->splitOutputStreams()->assertErrorOutputNotContains('admin user') 结合使用 ->splitOutputStreams()->dump() // 转储() 状态代码/输出和 continue->dd() // dd() 状态代码/输出; // 测试交互式命令TestCommand::for(new CreateUserCommand(/** args... */)) ->addInput('kbond') ->addOption('--no-interaction') // 如果提供了输入,命令将以交互方式运行,使用此选项禁用->execute() ->断言成功() ->assertOutputContains('创建普通用户“kbond”') ;// 访问结果$result = TestCommand::for(new CreateUserCommand(/** args... */))->execute();$result->statusCode();$result->output(); $结果->错误输出(); } }
我的班级 {private string $privateProperty = '私有值';私有函数 privateMethod(): string{return '私有返回值'; } }$myClass = new Myclass();
这就是如何使用invade
函数获取私有财产的值。
侵入($myClass)->privateProperty; // 返回“私有值”
invade
功能还允许您更改私有值。
入侵($myClass)->privateProperty = '更改值';入侵($myClass)->privateProperty; // 返回“改变后的值”
使用invade
你还可以调用私有函数。
侵入($myClass)->privateMethod(); // 返回“私有返回值”