proklung / phpunit-testing-tools
PHPUNIT testing tools.
Requires
- ext-json: *
- brain/monkey: ^2.6.0
- dg/bypass-finals: ^1.3
- dms/phpunit-arraysubset-asserts: ^0.3.0
- estahn/phpunit-json-assertions: ^v4.0.0
- fakerphp/faker: ^1
- friendsofphp/proxy-manager-lts: ^1.0
- guzzlehttp/guzzle: ^6.0 || ^7.0
- helmich/phpunit-json-assert: ^3.4
- illuminate/container: ~6 | ~7 | ~8
- illuminate/support: ~6 | ~7 | ~8
- mockery/mockery: ^1.4
- php-mock/php-mock-mockery: ^1.3
- phpstan/extension-installer: ^1.1
- phpstan/phpstan: ^0.12.64 || ^1.0.0
- phpstan/phpstan-beberlei-assert: ^0.12.4 || ^1.0.0
- phpstan/phpstan-deprecation-rules: ^0.12.6 || ^1.0.0
- phpstan/phpstan-doctrine: ^0.12.26 || ^1.0.0
- phpstan/phpstan-mockery: ^0.12.11 || ^1.0.0
- phpstan/phpstan-phpunit: ^0.12.17 || ^1.0.0
- phpstan/phpstan-symfony: ^0.12.12 || ^1.0.0
- phpunit/phpunit: ^7.5.2 || ^8.0 || ^9.0
- psalm/plugin-mockery: ^0.9.0
- psalm/plugin-symfony: ^2.4 || ^3
- squizlabs/php_codesniffer: ^3.6.0
- symfony/config: ^4.4 || ^5.0
- symfony/dependency-injection: ^4.4 || ^5.0
- symfony/dom-crawler: ^4.4 || ^5.0
- symfony/framework-bundle: ^4.4 || ^5.0
- symfony/http-kernel: ^4.4 || ^5.0
- symfony/mailer: ^4.4 || ^5.0
- symfony/mime: ^4.4 || ^5.0
- symfony/property-info: ^4.4 || ^5.0
- symfony/routing: ^4.4 || ^5.0
- symfony/yaml: ^4.4 || ^5.0
- vimeo/psalm: ^4.8.1
Requires (Dev)
- icanhazstring/composer-unused: ^0.7.5
- dev-master
- 1.5.8
- 1.5.7
- 1.5.6
- 1.5.5
- 1.5.4
- 1.5.3
- 1.5.2
- 1.5.1
- 1.5.0
- 1.4.9
- 1.4.8
- 1.4.7
- 1.4.6
- 1.4.5
- 1.4.4
- 1.4.3
- 1.4.2
- 1.4.1
- 1.4.0
- 1.3.9
- 1.3.8
- 1.3.7
- 1.3.6
- 1.3.5
- 1.3.4
- 1.3.3
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.95
- 1.2.9
- 1.2.8
- 1.2.7
- 1.2.6
- 1.2.5
- 1.2.4
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.0
- 1.0.16
- 1.0.15
- 1.0.14
- 1.0.13
- 1.0.12
- 1.0.11
- 1.0.10
- 1.0.9
- 1.0.8
- 1.0.7
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
This package is auto-updated.
Last update: 2025-07-10 12:21:35 UTC
README
INTERNAL
Установка
composer require --dev proklung/phpunit-testing-tools
Всякое
Как построить тестовый контейнер
Создать класс:
use Prokl\TestingTools\Base\BaseTestCase;
use Prokl\TestingTools\Tools\Container\BuildContainer;
class ContainerAwareBaseTestCase extends BaseTestCase
{
/**
* @inheritDoc
* @throws Exception
*/
protected function setUp(): void
{
$this->container = static::$testContainer = BuildContainer::getTestContainer(
[
'dev/test_container.yaml',
'dev/local.yaml'
],
'/Resources/config',
[new SampleCompilerPass()], // Опциональный параметр - кастомные compiler passes,
'dev', // Окружение. По умолчанию - dev
true // Debug. По умолчанию - true,
['service_to_mock'] // Сервисы, подлежащие мокингу (см. подраздел Моки сервисов)
);
parent::setUp();
}
}
Отнаследовать от него тест.
Подгрузятся конфиги сервисов из указанных файлов по указанному пути (относительно DOCUMENT_ROOT тестов).
Мокинг сервисов для функциональных тестов
Механизм (на базе создания прокси-сервисов по заданному списку) взят из бандла и адаптирован под локальные нужды.
use Prokl\TestingTools\Tools\ServiceMocker;
use Prokl\TestingTools\Base\BaseTestCase;
class MyTest extends BaseTestCase
{
use RestoreServiceContainer;
protected function setUp(): void
{
parent::setUp();
$this->container = BuildContainer::getTestContainer(
[
'test_container.yaml'
],
'/../../../../tests/Standalone/Resource/config',
[],
'dev',
true,
['filesystem.local.adapter'] // Сервис, который будет заменен моком.
);
}
public function testFoo()
{
// For all calls
ServiceMock::all($this->container->get('filesystem.local.adapter'), 'getAdapter', function () {
return new Local(
$_SERVER['DOCUMENT_ROOT'] . '/test/');
});
$result = $this->container->get('filesystem.local.adapter');
// For only the next call
ServiceMock::next($this->container->get('filesystem.local.adapter'), 'getAdapter', function () {
return new Local(
$_SERVER['DOCUMENT_ROOT'] . '/test/');
});
// This will queue a new callable
ServiceMock::next($this->container->get('filesystem.local.adapter'), 'getAdapter', function () {
throw new \InvalidArgument('getAdapter can call once time!');
});
$mock = // create a PHPUnit mock or any other mock you want.
ServiceMocker::swap($this->container->get('filesystem.local.adapter'), $mock);
// ...
$service = $this->container->get('filesystem.local.adapter');
$result = $service->getAdapter(); // Метод сервиса (или сервис целиком) подменен.
}
protected function tearDown(): void
{
// To make sure we don't affect other tests
ServiceMock::resetAll();
// You can include the RestoreServiceContainer trait to automatically reset services
}
}
BootTestKernelTrait
use Prokl\TestingTools\Traits\BootTestKernelTrait;
class ExampleTest extends \Prokl\TestingTools\Base\BaseTestCase
{
use BootTestKernelTrait;
protected function setUp(): void
{
parent::setUp();
$container = new ContainerBuilder();
// ... Наполнение тестового контейнера.
self::$kernel = $this->bootTestKernel($container);
}
}
CommandTestCase
Базовый класс для тестирования консольных команд.
Методы:
executeCommand(Command $commandInstance, string $commandName, array $params = [])
- вернет то, что команда вывела на экран.runCommand(Command $command, $input = [])
- вернет результат выполнения методаexecute
команды.
Трэйт DefaultDataProviders
Несколько общих дата-провайдеров
provideEmptyValue
- пустые значения.provideEmptyScalarValue
- пустые скалярные значенияprovideBooleanValue
- булевы значенияprovideDateTimeInstance
- инстанц DateTimeprovideNotExistingFilePath
- путь к несуществующему файлу
Мокер функций
Обертка над.
Пример (в тесте, унаследованном от BaseTestCase
):
// Замокается полностью (т.е. не важно с какими параметрами пройдет вызов) функция in_the_loop
$this->mockerFunctions->setNamespace('\Tests\API')
->full('in_the_loop', true)
->mock();
Namespace
- пространство имен, в котором мокается функция.
Или частичное моканье (в зависимости от аргументов):
// При вызове get_cat_name с аргументом $this->idCategory вернет Mocked category
$this->mockerFunctions->setNamespace('Test\API\Entity')
->partial('get_cat_name', 'Mocked category', $this->idCategory)
->partial('category_description', 'Mocked category description', $this->idCategory)
->mock();
При использовании этой фичи рекомендуется (во избежании проблем) на тест ставить аннотации:
/**
* data()
*
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
Трэйт ServiceLocatorConstructorTrait
Конструктор сервис-локаторов Symfony для тестов.
Метод:
constructServiceLocator(array $config)
- где$config
массив вида:
$object = new ClassName();
$config = [
'service_key' => ClassName::class,
'service_key2' => $object,
];
Если передать название класса в конфиге, то внутри метода класс будет инстанцирован.
Console test
Форк пакета
use App\Command\CreateUserCommand;
use Prokl\TestingTools\Base\BaseTestCase;
use Prokl\TestingTools\Tools\Console\InteractsWithConsole;
use Prokl\TestingTools\Traits\BootTestKernelTrait;
class CreateUserCommandTest extends BaseTestCase
{
use InteractsWithConsole;
use BootTestKernelTrait;
protected function setUp(): void
{
parent::setUp();
$container = new ContainerBuilder();
$container->setDefinition(
IntegrityCheck::class,
new Definition(IntegrityCheck::class, [])
)->setTags(['console.command' => ['command' => 'module:еуые']])->setPublic(true);
self::$kernel = $this->bootTestKernel($container);
$this->cliApplication = new \Symfony\Bundle\FrameworkBundle\Console\Application(self::$kernel);
$this->cliApplication->add($container->get(IntegrityCheck::class));
}
public function test_can_create_user(): void
{
$this->executeConsoleCommand('create:user kbond --admin --role=ROLE_EMPLOYEE --role=ROLE_MANAGER')
->assertSuccessful() // command exit code is 0
->assertOutputContains('Creating admin user "kbond"')
->assertOutputContains('with roles: ROLE_EMPLOYEE, ROLE_MANAGER')
->assertOutputNotContains('regular user')
;
// advanced usage
$this->consoleCommand(CreateUserCommand::class) // can use the command class or "name"
->splitOutputStreams() // by default stdout/stderr are combined, this options splits them
->addArgument('kbond')
->addOption('--admin') // with or without "--" prefix
->addOption('role', ['ROLE_EMPLOYEE', 'ROLE_MANAGER'])
->addOption('-R') // shortcut options require the "-" prefix
->addOption('-vv') // by default, output has normal verbosity, use the standard options to change (-q, -v, -vv, -vvv)
->addOption('--ansi') // by default, output is undecorated, use this option to decorate
->execute() // run the command
->assertSuccessful()
->assertStatusCode(0) // equivalent to ->assertSuccessful()
->assertOutputContains('Creating admin user "kbond"')
->assertErrorOutputContains('this is in stderr') // used in conjunction with ->splitOutputStreams()
->assertErrorOutputNotContains('admin user') // used in conjunction with ->splitOutputStreams()
->dump() // dump() the status code/outputs and continue
->dd() // dd() the status code/outputs
;
// testing interactive commands
$this->executeConsoleCommand('create:user', ['kbond'])
->assertSuccessful()
->assertOutputContains('Creating regular user "kbond"')
;
// advanced testing interactive commands
$this->consoleCommand(CreateUserCommand::class)
->addInput('kbond')
->addOption('--no-interaction') // commands are run interactively if input is provided, use this option to disable
->execute()
->assertSuccessful()
->assertOutputContains('Creating regular user "kbond"')
;
// access result
$result = $this->executeConsoleCommand('create:user');
$result->statusCode();
$result->output();
$result->errorOutput();
}
}
Или:
use App\Command\CreateUserCommand;
use PHPUnit\Framework\TestCase;
use Prokl\TestingTools\Tools\Console\TestCommand;
class CreateUserCommandTest extends TestCase
{
public function test_can_create_user(): void
{
TestCommand::for(new CreateUserCommand(/** args... */))
->splitOutputStreams() // by default stdout/stderr are combined, this options splits them
->addArgument('kbond')
->addOption('--admin') // with or without "--" prefix
->addOption('role', ['ROLE_EMPLOYEE', 'ROLE_MANAGER'])
->addOption('-R') // shortcut options require the "-" prefix
->addOption('-vv') // by default, output has normal verbosity, use the standard options to change (-q, -v, -vv, -vvv)
->addOption('--ansi') // by default, output is undecorated, use this option to decorate
->execute()
->assertSuccessful()
->assertStatusCode(0) // equivalent to ->assertSuccessful()
->assertOutputContains('Creating admin user "kbond"')
->assertErrorOutputContains('this is in stderr') // used in conjunction with ->splitOutputStreams()
->assertErrorOutputNotContains('admin user') // used in conjunction with ->splitOutputStreams()
->dump() // dump() the status code/outputs and continue
->dd() // dd() the status code/outputs
;
// testing interactive commands
TestCommand::for(new CreateUserCommand(/** args... */))
->addInput('kbond')
->addOption('--no-interaction') // commands are run interactively if input is provided, use this option to disable
->execute()
->assertSuccessful()
->assertOutputContains('Creating regular user "kbond"')
;
// access result
$result = TestCommand::for(new CreateUserCommand(/** args... */))->execute();
$result->statusCode();
$result->output();
$result->errorOutput();
}
}
Прочее
Invader (из пакета)
class MyClass
{
private string $privateProperty = 'private value';
private function privateMethod(): string
{
return 'private return value';
}
}
$myClass = new Myclass();
This is how you can get the value of the private property using the invade
function.
invade($myClass)->privateProperty; // returns 'private value'
The invade
function also allows you to change private values.
invade($myClass)->privateProperty = 'changed value';
invade($myClass)->privateProperty; // returns 'changed value
Using invade
you can also call private functions.
invade($myClass)->privateMethod(); // returns 'private return value'