在我的PHP应用程序中,我以后在数据访问中使用学说ORM。在此层中,我有一个服务,例如通常使用学说EntityManager的存储库。在这些服务中,执行某种形式修改的方法通常遵循以下模式:
public function modifyStuff( /* ... */ ) {
try {
$stuff = $this->entityManager->find( /* ... */ )
}
catch ( ORMException $ex ) {
/* ... */
}
// Poke at $stuff
try {
$this->entityManager->persist( $stuff );
$this->entityManager->flush();
}
catch ( ORMException $ex ) {
/* code that needs to be tested */
}
}
我正在尝试找到一种方法来测试第二个捕获块中的代码:处理写失败的代码。因此,在我的测试中,我需要在写东西时进行实体管理员。自然,我想最大程度地减少测试中的绑定,以实现此存储库(即使用哪些学说方法(以及EntityManager界面和实现本身。理想情况下,我可以做
之类的事情$entityManager = new TestEntityManager();
$entityManager->throwOnWrite();
之后EntityManager正常运行,除非它会插入写作。(我的存储库有这样的测试双打。(
我尝试使用phpunit模拟API如下:
$entityManager = $this->getMockBuilder( EntityManager::class )->disableOrgninalConstructor()->getMock()
$entityManager->expects( $this->any() )
->method( 'persist' )
->willThrowException( new ORMException() );
这不是理想的选择,因为现在我的测试与持久方法结合在一起,尽管这不是一个问题。但是,这是行不通的,因为为了使该服务运行其构造函数,需要一些参数。然后我尝试了
$entityManager =
$this->getMockBuilder( EntityManager::class )
->setConstructorArgs( [
$this->entityManager->getConnection(),
$this->entityManager->getConfiguration(),
$this->entityManager->getEventManager()
] )
->getMock();
发现EntityManager构造函数不是公开的。因此,我似乎无法使用Phpunit模拟API。
关于如何使EntityManager进行写入或以其他方式测试应该处理该案例的代码的任何想法?
您可以通过从flush事件处理程序中抛出此类例外来模拟写失败。考虑此示例:
$p = new EntityProduct();
$p->setName("Test Product");
$em->persist($p);
$em->flush();
$em->getEventManager()->addEventListener(DoctrineORMEvents::onFlush, new WriteErrorListener());
// Nothing changed, no exceptions.
$p->setName("Test Product");
$em->flush();
try {
$p->setName("Name changed");
$em->flush();
echo "nn UNEXPECTEDnn";
} catch (DoctrineORMORMException $ex) {
echo $ex->getMessage() . "n";
}
write errlistener:
use DoctrineORMQueryQueryException;
class WriteErrorListener
{
public function onFlush(DoctrineORMEventOnFlushEventArgs $eventArgs)
{
$em = $eventArgs->getEntityManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityInsertions() as $entity) {
// You can inspect $entity and provide additional information
throw new QueryException('[Test condition] Insertion of entity pending');
}
foreach ($uow->getScheduledEntityUpdates() as $entity) {
throw new QueryException('[Test condition] Update of entity pending');
}
// And so on...
}
}
运行:
$ php app.php
[Test condition] Update of entity pending