Symfony 5.4与PHPUnit 9.5测试时实体管理器不共享如何解决?
解决测试与应用代码使用不同EntityManager的问题
在Symfony 5.4 + PHPUnit 9.5的WebTestCase场景下,你遇到的问题根源是:测试类中通过static::getContainer()获取的EntityManager,和模拟HTTP请求时应用代码使用的EntityManager并非同一个实例(或存在缓存隔离),导致测试中创建的实体在请求上下文里无法被读取。
以下是两种可行的解决方法:
方法一:统一使用Client容器的EntityManager
直接从测试客户端的容器中获取EntityManager,确保测试操作和应用请求使用完全相同的实体管理器实例:
修改你的测试类代码:
<?php use Doctrine\ORM\EntityManager; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class MyTest extends WebTestCase { protected EntityManager $entity_manager; protected function setUp(): void { // 先创建测试客户端 static::$client = static::createClient(); // 从客户端容器获取EntityManager $this->entity_manager = static::$client->getContainer()->get('doctrine')->getManager(); } public function testShouldCreateAnEntityThatIsVisibleInTheAppCode() { $user = new User(); $user->setFirstName('Joe'); $user->setLastName('Bloggs'); $user->setEmail('joe.bloggs@example.com'); $this->entity_manager->persist($user); $this->entity_manager->flush(); // 请求时无需指定完整域名,用相对路径即可 $crawler = static::$client->request('GET', '/admin/show-users'); $this->assertStringContainsString('joe.bloggs@example.com', $crawler->html()); } }
方法二:清除Client侧EntityManager的缓存
如果你需要保留测试容器的EntityManager,可在flush后清除客户端容器中EntityManager的一级缓存,强制它从数据库重新读取实体:
public function testShouldCreateAnEntityThatIsVisibleInTheAppCode() { $user = new User(); $user->setFirstName('Joe'); $user->setLastName('Bloggs'); $user->setEmail('joe.bloggs@example.com'); $this->entity_manager->persist($user); $this->entity_manager->flush(); // 获取客户端的EntityManager并清除缓存 $clientEntityManager = static::$client->getContainer()->get('doctrine')->getManager(); $clientEntityManager->clear(); $crawler = static::$client->request('GET', '/admin/show-users'); $this->assertStringContainsString('joe.bloggs@example.com', $crawler->html()); }
额外注意事项
- 测试中请求路径建议用相对路径(如
/admin/show-users),而非完整域名,避免环境配置问题。 - Symfony的WebTestCase默认会在每个测试结束后回滚事务,无需担心测试数据污染数据库。
内容的提问来源于stack exchange,提问作者CJ Dennis
相关产品推荐
相关产品推荐

