首页  >  文章  >  后端开发  >  Symfony 与 Testcontainers 的集成测试

Symfony 与 Testcontainers 的集成测试

WBOY
WBOY原创
2024-09-12 10:23:00467浏览

免责声明:我不是神圣实体。我所说的并不是绝对的真理。甚至不要害怕质疑世界,因为它可能是错的,而不是你。

今天对于任何人来说,自动化测试对于保持软件的质量和完整性的重要性都不是秘密,通常我们会谈论很多单元测试,但是今天,我们将更多地关注到 Symfony 框架中的集成测试。

我没有耐心,给我看代码!

好吧好吧!如果你没有耐心阅读这篇文章,我有一个测试项目,在下面的链接中实现了本文。

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

Symfony 框架和集成测试

如今,Symfony 框架是 PHP 领域最成熟、最稳定的框架之一,它拥有各种良好的实施解决方案,例如集成测试。但是,我个人一直认为,虽然集成测试本身很容易,但为测试提供外部依赖项并不总是那么容易,例如数据库。

即使使用像 Docker 这样的解决方案,我仍然意识到有必要以某种方式提供外部依赖项以进行测试,但是,存在一个非常有趣的解决方案,可以使这一步变得更加容易,即 Testcontainers。

测试容器

Testcontainers 是一个开源框架,可让您以简单的方式提供使用 Docker 所需的任何外部依赖项,如数据库、消息代理、缓存系统或容器中的依赖项。

Testcontainers 相对于 Docker compose 或其他容器编排方式的一大优势是您可以对容器的配置进行编码,并且现在已经支持 Golang、Java、.NET、Node.js、Python、Rust 等各种语言其他语言,当然还有 PHP!

我第一次接触 Testcontainers 是在 Golang 的一个项目中,我非常喜欢配置 MongoDB 容器来进行存储库测试的功能,之后,我决定使用 Symfony 框架在我的个人 PHP 项目中做同样的事情。

Symfony + 测试容器 = ❤️

Symfony 最大的优势之一是支持与 PHPUnit 集成进行测试,并使用功能内核来执行测试所需的引导。

虽然 Testcontainers 支持 PHP,但它们的实现是最近才实现的,您可以在 https://github.com/testcontainers/testcontainers-php 查看它。

下面我们有一个MySQL 8.0容器的实现,它是这个项目的外部依赖,以及Symfony内核的启动,数据库和模式的创建。

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

有了这个,我们就有了将执行测试本身的类的基础类,如下所示。

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

运行测试套件时,您可以看到与仅具有模拟行为的测试的单元测试相比,测试执行速度较慢,但​​这是正常的,因为在此过程中,Testcontainers 正在配置您定义在测试中使用的容器.

Integration tests on Symfony with Testcontainers

Integration tests on Symfony with Testcontainers

最后,有了这个设施,就可以做一些疯狂的事情,比如 100% 的覆盖率。不相信吗?您可以在 https://joubertredrat.github.io/symfony-testcontainers 亲自查看。

就这样,下期见!

以上是Symfony 与 Testcontainers 的集成测试的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn