zalas/phpunit-injector

将PSR-11依赖注入容器的服务注入到PHPUnit测试用例中

v2.5.1 2024-01-24 17:06 UTC

README

Build

提供一个PHPUnit监听器,将PSR-11依赖注入容器的服务注入到PHPUnit测试用例中。

将服务注入到实现Zalas\Injector\PHPUnit\TestCase\ServiceContainerTestCase的测试用例的任何带有@inject标签的属性。

还提供了与Symfony DependencyInjection组件的集成。

安装

Composer

composer require --dev zalas/phpunit-injector

Phar

此扩展也作为PHAR分发,可以从最新的Github发行版下载。

将扩展放在您的PHPUnit扩展目录中。请记住,在您的phpunit.xml中指导PHPUnit加载扩展

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.0/phpunit.xsd"
         extensionsDirectory="tools/phpunit.d"
>
</phpunit>

配置

PHPUnit配置文件中启用服务注入监听器

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.0/phpunit.xsd">

    <!-- ... -->

    <listeners>
        <listener class="Zalas\Injector\PHPUnit\TestListener\ServiceInjectorListener" />
    </listeners>
</phpunit>

用法

要使用任何PSR-11服务容器注入服务,实现Zalas\Injector\PHPUnit\TestCase\ServiceContainerTestCase并使用@inject标签标记选定的属性

use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Zalas\Injector\PHPUnit\TestCase\ServiceContainerTestCase;

class ServiceInjectorTest extends TestCase implements ServiceContainerTestCase
{
    /**
     * @inject
     */
    private SerializerInterface $serializer;

    /**
     * @inject logger
     */
    private LoggerInterface $logger;

    public function testThatServicesAreInjected()
    {
        $this->assertInstanceOf(SerializerInterface::class, $this->serializer, 'The service is injectd by its type');
        $this->assertInstanceOf(LoggerInterface::class, $this->logger, 'The service is injected by its id');
    }

    public function createServiceContainer(): ContainerInterface
    {
        // create a service container here
    }
}

服务通过其类型或@inject标签中给出的id找到。

createServiceContainer方法通常由基测试用例或特质提供。在Symfony的情况下,此包提供了一个这样的特质(见下一节)。

Symfony测试容器(Symfony >= 4.1)

Zalas\Injector\PHPUnit\Symfony\TestCase\SymfonyTestContainer特质提供了对测试容器(在Symfony 4.1中引入)的访问。将此特质包含在实现ServiceContainerTestCase的测试用例中将使服务注入到注释的属性

use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Zalas\Injector\PHPUnit\Symfony\TestCase\SymfonyTestContainer;
use Zalas\Injector\PHPUnit\TestCase\ServiceContainerTestCase;

class ServiceInjectorTest extends TestCase implements ServiceContainerTestCase
{
    use SymfonyTestContainer;

    /**
     * @inject
     */
    private SerializerInterface $serializer;

    /**
     * @inject logger
     */
    private LoggerInterface $logger;

    public function testThatServicesAreInjected()
    {
        $this->assertInstanceOf(SerializerInterface::class, $this->serializer, 'The service is injectd by its type');
        $this->assertInstanceOf(LoggerInterface::class, $this->logger, 'The service is injected by its id');
    }
}

请注意,在框架包的测试环境配置中需要将test设置为true

framework:
    test: true

尽管Symfony自动将服务设置为私有,但测试容器使它们在测试中可用。请注意,这只发生在实际用于您的应用程序(因此注入到公共服务,例如控制器)的私有服务。如果服务在任何地方都没有注入,它将被容器编译器删除。

用于引导容器的内核以类似于FrameworkBundle中已知的KernelTestCase的方式创建。支持类似的环境变量。

  • KERNEL_CLASS 必需 - 实例化以创建服务容器的内核类
  • APP_ENV 默认:test - 内核环境
  • APP_DEBUG 默认:false - 内核调试标志

这些可以通过phpunit.xml配置,或通过全局变量

Symfony容器(Symfony 3.4 & 4.0)

《Zalas\Injector\PHPUnit\Symfony\TestCase\SymfonyContainer》特性为用户提供完整的Symfony容器访问权限,并且可以与任何版本的Symfony一起使用。与Symfony 4.1中测试容器的方案相反,此版本即使服务在您的应用程序中没有被使用,也会被编译器删除,也能提供每个服务的访问权限。这应被视为一种限制而不是功能。

use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Zalas\Injector\PHPUnit\Symfony\TestCase\SymfonyContainer;
use Zalas\Injector\PHPUnit\TestCase\ServiceContainerTestCase;

class ServiceInjectorTest extends TestCase implements ServiceContainerTestCase
{
    use SymfonyContainer;

    /**
     * @inject
     */
    private SerializerInterface $serializer;

    /**
     * @inject logger
     */
    private LoggerInterface $logger;

    public function testThatServicesAreInjected()
    {
        $this->assertInstanceOf(SerializerInterface::class, $this->serializer, 'The service is injectd by its type');
        $this->assertInstanceOf(LoggerInterface::class, $this->logger, 'The service is injected by its id');
    }
}

由于测试容器直到Symfony 4.1才可用,您还需要注册《Zalas\Injector\PHPUnit\Symfony\Compiler\ExposeServicesForTestsPass》编译器传递

use Zalas\Injector\PHPUnit\Symfony\Compiler\ExposeServicesForTestsPass;

class Kernel extends BaseKernel
{
    // ...

    protected function build(ContainerBuilder $container)
    {
        if ('test' === $this->getEnvironment()) {
            $container->addCompilerPass(new ExposeServicesForTestsPass());
        }
    }
}

编译器传递确保即使私有服务也可用于测试。

贡献

请阅读贡献指南,了解如何为该项目做出贡献。请注意,该项目遵循《贡献者行为准则》。参与本项目即表示您同意遵守其条款。