search
HomeBackend DevelopmentPHP TutorialIntegration tests on Symfony with Testcontainers

Disclaimer: I'm not a divine entity. What I say is not an absolute truth. Don't be afraid to question even the world, because it might be wrong, not you.

Today isn't a secret for nobody the importance of automated tests for keeping quality and integrity of your software and normally we talk much about unit tests, but, today, we will focus more in integration tests into Symfony Framework.

I have no patience, show me the code!

Okay okay! If you have no patience for reading the article, I have a test project with the implementation of this article in link below.

https://github.com/joubertredrat/symfony-testcontainers

Symfony Framework and integration tests

Today Symfony Framework is one of most mature and stable frameworks in PHP universe and it have various good implemented solutions, as integration tests for example. But, personally I always thought that although is easy to do integration tests itself, to provide external dependencies for test It wasn't always so easy, as databases for example.

Even with a solutions like Docker, I still realized necessity to provide the external dependencies in a way for the tests, but, exists a very interesting solution that can make this step much easier, the Testcontainers.

Testcontainers

Testcontainers is an open source framework that let you provide in a easy way any external dependency that you need using Docker, as databases, message broker, cache system, or ever dependency in container.

The big advantages of Testcontainers in relation to Docker compose or other way of container orchestration is you can code the provisioning of container, and today already have support to Golang, Java, .NET, Node.js, Python, Rust, various other languages and of course, PHP too!

My first contact with Testcontainers was in a project in Golang and I liked so much the facility of provisioning MongoDB container to do the repository tests and after that, I decided to do same thing in my personal project in PHP using Symfony Framework.

Symfony Testcontainers = ❤️

One of biggest advantages of Symfony is the support to do tests integrated with PHPUnit and with a functional kernel to do the bootstrap necessary for the tests.

Although Testcontainers have support to PHP, their implementation is recent and you can view it at https://github.com/testcontainers/testcontainers-php.

Below we have a implementation of MySQL 8.0 container, that is a external dependency of this project, and the boot of Symfony kernel, creation of database and schema.

class IntegrationTestCase extends KernelTestCase
{
    protected static ?MySQLContainer $container = null;

    public static function setUpBeforeClass(): void
    {
        parent::setUpBeforeClass();

        if (!static::$container) {
            static::$container = MySQLContainer::make('8.0', 'password');
            static::$container->withPort('19306', '3306');
            static::$container->run();

            $kernel = self::bootKernel();
            $container = $kernel->getContainer();

            $application = new Application($kernel);
            $application->setAutoExit(false);

            $application->run(
                new ArrayInput(['command' => 'doctrine:database:create', '--if-not-exists' => true])
            );

            $entityManager = $container->get('doctrine')->getManager();
            $metadata = $entityManager->getMetadataFactory()->getAllMetadata();
            $schemaTool = new SchemaTool($entityManager);
            $schemaTool->dropSchema($metadata);
            $schemaTool->createSchema($metadata);
        }
    }

    public static function tearDownAfterClass(): void
    {
        parent::tearDownAfterClass();

        if (static::$container instanceof MySQLContainer) {
            static::$container->remove();
        }
    }

With this, we have the basis class for the classes that will execute the tests itself, as example below.

class UserRepositoryTest extends IntegrationTestCase
{
    public function testSave(): void
    {
        $user = new User();
        $user->setName('John Doe');
        $user->setEmail('john@doe.local');

        $repo = $this->getRepository();
        $repo->save($user, true);

        self::assertNotNull($user->getId());
        self::assertIsInt($user->getId());
        self::assertTrue($user->getId() > 0);
    }

    public function testGetByEmail(): void
    {
        $user = new User();
        $user->setName('John Doe');
        $user->setEmail('john2@doe.local');

        $repo = $this->getRepository();
        $userNotFound = $repo->getByEmail($user->getEmail());
        self::assertNull($userNotFound);

        $repo->save($user, true);
        $userFound = $repo->getByEmail($user->getEmail());

        self::assertEquals($user->getEmail(), $userFound->getEmail());
    }

    protected function tearDown(): void
    {
        parent::tearDown();

        $connection = $this
            ->getContainer()
            ->get('doctrine')
            ->getManager()
            ->getConnection()
        ;
        $connection->executeStatement('TRUNCATE TABLE users');
    }

    protected function getRepository(): UserRepository
    {
        return $this->getContainer()->get(UserRepository::class);
    }
}

When running suite of tests, you can view that tests will execute slowly compared with unit tests of tests with just mocked behaviors, but this is normal, because during this process, Testcontainers is provisioning the container that you defined to use in tests.

Integration tests on Symfony with Testcontainers

Integration tests on Symfony with Testcontainers

Finally, with this facility, can be possible to do crazy things, like 100% of coverage. Don't believe it? You can see for yourself at https://joubertredrat.github.io/symfony-testcontainers.

That's it, see you next!

The above is the detailed content of Integration tests on Symfony with Testcontainers. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Solve the problem of displaying Urdu after MySQL multilingual character set garbled: host migrationSolve the problem of displaying Urdu after MySQL multilingual character set garbled: host migrationAug 04, 2025 pm 07:33 PM

This article explores in-depth the problem of multilingual (such as Urdu) characters displayed abnormally after a website is moved from one host to another. Although the server and table-level character set settings seem to be consistent, the root cause is that the character set encoding of the database table columns does not match. The article provides detailed diagnostic methods, SQL solutions, and best practices to prevent such problems, ensuring that multilingual content is displayed correctly.

Master JavaScript and PHP to implement rich text editor HTML content libraryMaster JavaScript and PHP to implement rich text editor HTML content libraryAug 04, 2025 pm 07:30 PM

This tutorial is intended to solve the problem that HTML tag content cannot be saved to the database correctly when using rich text editors such as TinyMCE or CKEditor. The article will elaborate on how to get the editor's complete HTML content through JavaScript and send it securely to the PHP backend, ultimately using preprocessing statements to store data containing HTML tags efficiently and securely into the database, while providing critical code examples and security best practices.

Complete Guide to Safely Save Rich Text Editor HTML Content to a Database in a Web ApplicationComplete Guide to Safely Save Rich Text Editor HTML Content to a Database in a Web ApplicationAug 04, 2025 pm 07:15 PM

This tutorial is intended to solve the problem that HTML format content cannot be saved to the database correctly when using rich text editors such as TinyMCE or CKEditor. We will introduce in detail how to correctly obtain the complete HTML content of the editor through JavaScript, and combine it with the PHP backend for safe and effective processing and storage, including client data extraction, server data reception, and crucial security protection measures to ensure that rich text content is complete and safely persisted.

Master the content library of rich text editors: the collaborative practice of JavaScript and PHPMaster the content library of rich text editors: the collaborative practice of JavaScript and PHPAug 04, 2025 pm 06:57 PM

This article details how to solve the problem that HTML tags cannot be saved to the database correctly when using rich text editors such as TinyMCE or CKEditor. The core solution is to use tinymce.activeEditor.getContent() in client JavaScript to accurately get the editor's complete HTML content and pass it correctly to the server. At the same time, it emphasizes that when receiving data in PHP backend, necessary security processing, such as SQL injection protection and XSS attack prevention, ensure data integrity and system security.

Save rich text editor content to database safely and efficiently using JavaScript and PHPSave rich text editor content to database safely and efficiently using JavaScript and PHPAug 04, 2025 pm 06:54 PM

This tutorial details how to insert HTML content generated by rich text editors such as TinyMCE or CKEditor safely into the database through JavaScript and PHP. The article will focus on how the client correctly obtains the editor content and builds the requested data, as well as how the server receives, verifies and uses preprocessing statements to prevent SQL injection, ensuring that the HTML tags are completely saved while ensuring data security.

Solve foreign key constraint error 1452 in Laravel: Data integrity and import strategySolve foreign key constraint error 1452 in Laravel: Data integrity and import strategyAug 04, 2025 pm 06:21 PM

When an SQLSTATE[23000]: Integrity constraint violation: 1452 error is encountered in a Laravel application, it usually means that when trying to insert or update data into a child table, the parent table record referenced by its foreign key does not exist. This is common in batch data import scenarios. The core reason is that the value of the external key field of the child table cannot be found in the parent table, or the data type and length of the two do not match. This article will explore the causes of this error in depth, provide specific diagnostic and resolution steps, and provide preventive measures.

Resolving SQL Foreign Key Constraint Failed: 1452 Error GuideResolving SQL Foreign Key Constraint Failed: 1452 Error GuideAug 04, 2025 pm 06:06 PM

This article aims to deeply analyze SQLSTATE[23000]: Integrity constraint violation: 1452 Foreign key constraint failure error. This error usually occurs when trying to insert or update child table data, but the parent table record it associated with does not exist, or the foreign key does not match the data type/length of the primary key. The tutorial will elaborate on the causes of errors, diagnosis methods, and provide targeted solutions to ensure database data integrity and relevance.

A comprehensive guide to resolving foreign key constraint conflicts in LaravelA comprehensive guide to resolving foreign key constraint conflicts in LaravelAug 04, 2025 pm 06:00 PM

This article aims to deeply analyze the common SQLSTATE[23000]: Integrity constraint violation: 1452 foreign key constraint errors in Laravel applications. We will explore the core reason for this error, that is, the child table references records that do not exist in the parent table or the foreign key field data type mismatch. The tutorial will provide detailed diagnostic methods, verification steps and targeted solutions, including data consistency checks and data type matching verification, and pay special attention to preventive measures when importing batch data to ensure data integrity and system stability.

See all articles

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools