All Projects → jakzal → phpunit-injector

jakzal / phpunit-injector

Licence: MIT license
Injects services from a PSR-11 dependency injection container to PHPUnit test cases

Programming Languages

PHP
23972 projects - #3 most used programming language
Makefile
30231 projects

Projects that are alternatives of or similar to phpunit-injector

BDTest
BDTest - A Testing Framework for .NET
Stars: ✭ 58 (-6.45%)
Mutual labels:  test, tests
Test Pack
A Symfony Pack for functional testing
Stars: ✭ 865 (+1295.16%)
Mutual labels:  test, tests
flyway-junit5-extensions
Flyway JUnit 5 Extension to clean / migrate your database in tests.
Stars: ✭ 14 (-77.42%)
Mutual labels:  test, tests
unittest expander
A library that provides flexible and easy-to-use tools to parameterize Python unit tests, especially those based on unittest.TestCase.
Stars: ✭ 12 (-80.65%)
Mutual labels:  test, tests
7182
Curso 7182 - Refatorando para testes de unidade
Stars: ✭ 21 (-66.13%)
Mutual labels:  test, tests
Telegraf-Test
Telegraf Test - Simple Test ToolKit of Telegram Bots
Stars: ✭ 22 (-64.52%)
Mutual labels:  test, tests
Capture Stream
Capture stream output.
Stars: ✭ 10 (-83.87%)
Mutual labels:  test, tests
Brainmonkey
Mocking utility for PHP functions and WordPress plugin API
Stars: ✭ 191 (+208.06%)
Mutual labels:  phpunit, tests
Should.js
BDD style assertions for node.js -- test framework agnostic
Stars: ✭ 1,908 (+2977.42%)
Mutual labels:  test, tests
Create Test Server
Creates a minimal Express server for testing
Stars: ✭ 117 (+88.71%)
Mutual labels:  test, tests
playwright-test
Run unit tests with several runners or benchmark inside real browsers with playwright.
Stars: ✭ 81 (+30.65%)
Mutual labels:  test, tests
arduino-ci-script
Bash script for continuous integration of Arduino projects
Stars: ✭ 25 (-59.68%)
Mutual labels:  test, tests
PixelTest
Fast, modern, simple iOS snapshot testing written purely in Swift.
Stars: ✭ 56 (-9.68%)
Mutual labels:  test, tests
dojos
Alguns desafios para os participantes dos grupos de estudo
Stars: ✭ 33 (-46.77%)
Mutual labels:  test, tests
mutode
Mutation testing for JavaScript and Node.js
Stars: ✭ 61 (-1.61%)
Mutual labels:  test, tests
node-bogota
🚀 Run tape tests concurrently with tap-spec output
Stars: ✭ 15 (-75.81%)
Mutual labels:  test, tests
Unit Testing Tips
Unit testing tips by examples in PHP
Stars: ✭ 318 (+412.9%)
Mutual labels:  phpunit, tests
Phpunit Easymock
Build PHPUnit mocks easily
Stars: ✭ 37 (-40.32%)
Mutual labels:  phpunit, tests
Cypress
Fast, easy and reliable testing for anything that runs in a browser.
Stars: ✭ 35,145 (+56585.48%)
Mutual labels:  test, tests
vscode-phpunit
The VS Code Test Explorer extension for PHPUnit
Stars: ✭ 100 (+61.29%)
Mutual labels:  test, phpunit

PHPUnit Injector

Build Status

Provides a PHPUnit listener to inject services from a PSR-11 dependency injection container to PHPUnit test cases.

Services are injected to test cases that implement Zalas\Injector\PHPUnit\TestCase\ServiceContainerTestCase to any property tagged with @inject.

Symfony DependencyInjection component integration is also provided.

Installation

Composer

composer require --dev zalas/phpunit-injector

Phar

The extension is also distributed as a PHAR, which can be downloaded from the most recent Github Release.

Put the extension in your PHPUnit extensions directory. Remember to instruct PHPUnit to load extensions in your phpunit.xml:

<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>

Configuration

Enable the service injector listener in the PHPUnit configuration file:

<?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>

Usage

To inject services using any PSR-11 service container, implement the Zalas\Injector\PHPUnit\TestCase\ServiceContainerTestCase and tag selected properties with @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
    }
}

The service is found by its type, or an id if it's given in the @inject tag.

The createServiceContainer method would be usually provided by a base test case or a trait. In case of Symfony, such a trait is provided by this package (see the next section).

Symfony Test Container (Symfony >= 4.1)

The Zalas\Injector\PHPUnit\Symfony\TestCase\SymfonyTestContainer trait provides access to the test container (introduced in Symfony 4.1). Including the trait in a test case implementing the ServiceContainerTestCase will make that services are injected into annotated properties:

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');
    }
}

Note that test needs to be set to true in your test environment configuration for the framework bundle:

framework:
    test: true

Even though services are automatically made private by Symfony, the test container makes them available in your tests. Note that this only happens for private services that are actually used in your app (so are injected into a public service, i.e. a controller). If a service is not injected anywhere, it's removed by the container compiler.

The kernel used to bootstrap the container is created in a similar way to the KernelTestCase known from the FrameworkBundle. Similar environment variables are supported:

  • KERNEL_CLASS required - kernel class to instantiate to create the service container
  • APP_ENV default: test - kernel environment
  • APP_DEBUG default: false - kernel debug flag

These could for example be configured in phpunit.xml, or via global variables.

Symfony Container (Symfony 3.4 & 4.0)

The Zalas\Injector\PHPUnit\Symfony\TestCase\SymfonyContainer trait gives access to the full Symfony Container and can be used with any Symfony version. Opposed to the Test Container approach for Symfony 4.1, this version provides access to each service even if it's not used by your application anywhere and would normally be removed by the compiler. This should be treated as a limitation rather than a feature.

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');
    }
}

Since the test container is not available until Symfony 4.1, you'll also have to register the Zalas\Injector\PHPUnit\Symfony\Compiler\ExposeServicesForTestsPass compiler pass:

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

class Kernel extends BaseKernel
{
    // ...

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

The compiler pass makes sure that even private services are available to be used in tests.

Contributing

Please read the Contributing guide to learn about contributing to this project. Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].