Codeception中Symfony Fixtures无法自动注入的问题
我写了一个简单的仓储测试用例:
class AmaRepositoryCest { public function _before(FunctionalTester $I) { $I->loadFixtures(AmaFixture::class); } public function testMe(FunctionalTester $I): void { $result = $I->grabService(AmaRepository::class)->getByUid(1); $I->assertEquals([2, 3], $result); } }
但因为AmaFixture中注入了服务,执行测试时报错:
[ArgumentCountError] Too few arguments to function
App\DataFixtures\AmaFixture::__construct(), 0 passed in
/application/vendor/codeception/module-doctrine/src/Codeception/Module/Doctrine.php
on line 727 and exactly 1 expected
奇怪的是执行php bin/console doctrine:fixtures:load命令却能正常运行。以下是我的Functional.suite.yml配置:
actor: FunctionalTester namespace: Tests modules: enabled: - Asserts - Tests\Support\Helper\Functional - Symfony: app_path: 'src' - Doctrine: depends: Symfony cleanup: true step_decorators: ~
环境版本:Symfony 6.1,Codeception 5.0
解决方案
问题根源是Codeception的Doctrine模块默认直接用new关键字实例化Fixture,不会通过Symfony容器处理依赖注入,导致Fixture的构造函数参数无法自动填充。
方法1:配置Doctrine模块使用Symfony容器加载Fixture
修改Functional.suite.yml中的Doctrine模块配置,添加fixture_loader: 'Symfony',让模块通过Symfony容器解析Fixture的依赖,和doctrine:fixtures:load命令的逻辑保持一致:
modules: enabled: # 保留其他已启用模块 - Doctrine: depends: Symfony cleanup: true fixture_loader: 'Symfony'
方法2:手动通过容器获取Fixture并加载
如果不想修改配置,也可以在测试方法中手动从容器获取Fixture实例,再调用Doctrine的Fixture执行器加载:
use Doctrine\ORM\EntityManagerInterface; use Doctrine\Common\DataFixtures\Executor\ORMExecutor; use Doctrine\Common\DataFixtures\Purger\ORMPurger; public function _before(FunctionalTester $I) { // 从容器获取Fixture实例 $fixture = $I->grabService(AmaFixture::class); $entityManager = $I->grabService(EntityManagerInterface::class); // 手动执行Fixture加载 $executor = new ORMExecutor($entityManager, new ORMPurger($entityManager)); $executor->execute([$fixture]); }
内容的提问来源于stack exchange,提问作者Majesty

