测试环境中的 Doctrine DBAL sql 记录器

Doctrine DBAL sql logger in test environment

我想在测试时使用 Doctrine\DBAL\Logging\SQLLogger 检查我的查询时间。

配置在config/packages/test/doctrine.yaml:

doctrine:
    dbal:
        dbname_suffix: '_test%env(default::TEST_TOKEN)%'
        logging:  true
        profiling: true

代码:

public function testSingleInsertTime()
{
    $maxTimeInMs = 0.1; // Please ignore this and the fact that I'm testing single insert. Actual code is different.

    $em = static::$entityManager;
    $em->getConfiguration()->setSQLLogger(new DebugStack());

    /** @var DebugStack */
    $sqlLogger = $em->getConfiguration()->getSQLLogger();

    $productState = (new ProductState())
        ->setId(123)
        ->setHash('EXP000276669cc123038419f265bf124')
    ;

    $em->persist($productState);
    $em->flush();

    dump($sqlLogger->queries);die; // HERE i get an empty array :(

    $actualTime = 1; // TODO: get from logger

    $this->assertGreaterThan($maxTimeInMs, $actualTime);
}

php bin/phpunit --filter testSingleInsertTime tests/Doctrine/ProductTest.php 调用刷新后我得到一个空数组。怎么了?

__

更新

看,即使是具有 dev 环境的简单控制器也会失败! 我的代码有问题。 Sql 记录器可能以其他方式工作。

use Doctrine\DBAL\Logging\DebugStack;

class DataDMLController extends AbstractController
{
    /**
     * @Route("/action", name="action")
     */
    public function action(EntityManagerInterface $em)
    {
        $em->getConfiguration()->setSQLLogger(new DebugStack());

        /** @var DebugStack */
        $sqlLogger = $em->getConfiguration()->getSQLLogger();

        $productState = (new ProductState())
            ->setId(124)
            ->setHash('EXP000276669cc123038419f265bf124')
        ;

        $em->persist($productState);
        $em->flush();

        dump($sqlLogger->queries); // an empty array!
        die;
        
        return new Response();
    }
}

解决方案是从连接获取配置(而不是直接从实体管理器)。

$em->getConnection()->getConfiguration()->setSQLLogger(new DebugStack());

我们必须了解 EntityManagerInterface 有自己的配置,Connection 也有自己的配置,所以我们有 2 种不同的配置,我们必须为 DBAL 组件和此类组件中的连接设置 sql 记录器管理执行查询。好吧,这不是实体管理器的角色,所以现在它变得清晰易懂了。

__

选项

logging:  true
profiling: true

不需要。