You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony 6.2:通用可用性测试中查询数据库的内核启动问题

解决Symfony测试数据提供者中内核提前启动的异常问题

核心问题根源

数据提供者的执行时机早于测试方法,在数据提供者里调用static::getContainer()会直接启动内核,而后续测试方法中的createClient()会再次尝试启动内核,触发LogicException。

可行解决方案

方案1:在测试类初始化阶段提前启动内核并复用容器

在测试类的setUpBeforeClass()方法中提前创建客户端,将容器实例保存为静态类属性,数据提供者直接复用这个已启动的容器:

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class BlogPostAvailabilityTest extends WebTestCase
{
    private static $container;

    public static function setUpBeforeClass(): void
    {
        $client = static::createClient();
        self::$container = $client->getContainer();
    }

    /**
     * @dataProvider blogPostUrlsProvider
     */
    public function testBlogPostAvailability(string $url): void
    {
        $client = static::createClient();
        $client->request('GET', $url);
        
        $this->assertResponseIsSuccessful();
    }

    public static function blogPostUrlsProvider(): iterable
    {
        /** @var \App\Repository\BlogPostRepository $repo */
        $repo = self::$container->get(\App\Repository\BlogPostRepository::class);
        $posts = $repo->findAll();

        foreach ($posts as $post) {
            yield [$post->getUrl()];
        }
    }
}

说明:setUpBeforeClass()在所有测试方法执行前仅运行一次,提前完成内核启动和容器保存,数据提供者直接复用实例,避免重复启动内核。

方案2:将仓库调用逻辑移至测试方法内

如果不需要为每篇文章生成独立测试用例,可把仓库查询和URL校验逻辑合并到单个测试方法中:

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class BlogPostAvailabilityTest extends WebTestCase
{
    public function testAllBlogPostsAreAvailable(): void
    {
        $client = static::createClient();
        $repo = $client->getContainer()->get(\App\Repository\BlogPostRepository::class);
        $posts = $repo->findAll();

        foreach ($posts as $post) {
            $client->request('GET', $post->getUrl());
            $this->assertResponseIsSuccessful(sprintf('校验失败:文章 "%s"', $post->getTitle()));
        }
    }
}

说明:该方式避免了数据提供者中启动内核的冲突,适合不需要单独统计单篇文章测试结果的场景。

方案3:通过测试依赖提前初始化内核

创建前置测试方法完成内核启动和仓库实例化,数据提供者依赖该方法的执行结果:

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class BlogPostAvailabilityTest extends WebTestCase
{
    private static $repo;

    public function testKernelBoot(): void
    {
        $client = static::createClient();
        self::$repo = $client->getContainer()->get(\App\Repository\BlogPostRepository::class);
        $this->assertNotNull(self::$repo);
    }

    /**
     * @dataProvider blogPostUrlsProvider
     * @depends testKernelBoot
     */
    public function testBlogPostAvailability(string $url): void
    {
        $client = static::createClient();
        $client->request('GET', $url);
        
        $this->assertResponseIsSuccessful();
    }

    public static function blogPostUrlsProvider(): iterable
    {
        $posts = self::$repo->findAll();

        foreach ($posts as $post) {
            yield [$post->getUrl()];
        }
    }
}

说明:@depends注解确保testKernelBoot()优先执行,提前完成仓库初始化,数据提供者可直接使用实例,不会触发内核重复启动。

关键注意事项

  • 数据提供者为静态方法,需用静态属性保存容器或仓库实例
  • 禁止在数据提供者中直接调用static::getContainer(),必须通过提前启动的客户端获取容器
  • Symfony的WebTestCase内核默认是单例,但数据提供者执行时内核未完成正确初始化,会导致后续createClient()报错

内容的提问来源于stack exchange,提问作者Olray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 05:22:22