测试学说EntityManager写失败



在我的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

相关内容

  • 没有找到相关文章