如何在 Symfony 中为使用 queryBuilder 构建的 MongoDB 查询编写单元测试

How to write a unit test for MongoDB query built with queryBuilder in Symfony

我正在努力理解如何为这段代码编写单元测试

$qb = $documentManager->getRepository('Document:Account')->createQueryBuilder();
$qb->remove(\project\Document\Account::class)->field('username')
   ->equals($userAccount->getUsername())->getQuery()->execute();

这是我尝试模拟这部分的尝试

$account = new account();
$documentAccount = $this->createMock(documentAccount::class);
$this->dm->expects($this->any())->method('getRepository')
     ->with($documentAccount)
     ->willReturn($account);

但是当控件到达这一部分时,我一直收到这个错误。

提前致谢。

PHP单位:PHP单位8.5.21

PHP: PHP 7.2.34

Symfony:Symfony 4.4.18

错误出现是因为你没有从$documentManager开始模拟,你的测试用例显然必须从它开始。

我曾经使用 Prophecy 进行测试,但使用原生 MockBuilder 时逻辑相同。 考虑到我不知道真实的 class 你的用例正在使用,所以我让你大致了解你必须做什么,看看下面的代码:

    $queryBuilder = $this->createMock(QueryBuilder::class);
    $documentManager = $this->createMock(DocumentMannager::class);
    $documentAccount = $this->createMock(Document::Account);
    
    $documentManager
        ->expects($this->once())
        ->method('getRepository')
        ->with('Document:Account')
        ->willReturn($documentAccount)
    ;

    $documentAccount
        ->expects($this->once())
        ->method('createQueryBuilder')
        ->willReturn($queryBuilder)
    ;
    
    $queryBuilder
        ->expects($this->once())
        ->method('remove')
        ->with(\project\Document\Account::class)
        ->willReturn($queryBuilder)
    ;
    
    $queryBuilder
        ->expects($this->once())
        ->method('field')
        ->with('username')
        ->willReturn($queryBuilder)
    ;
    
    $queryBuilder
        ->expects($this->once())
        ->method('equals')
        ->withAnyParameters()
        ->willReturn($queryBuilder)
    ;
    
    $queryBuilder
        ->expects($this->once())
        ->method('getQuery')
        ->willReturn($queryBuilder)
    ;
    
    
    $queryBuilder
        ->expects($this->once())
        ->method('execute')
    ;

我们精确地模拟了原始代码的每个调用

$qb = $documentManager->getRepository('Document:Account')->createQueryBuilder();
$qb->remove(\project\Document\Account::class)->field('username')
   ->equals($userAccount->getUsername())->getQuery()->execute();

这是我修复它的方法。这可能对遇到类似问题的人有帮助

$accountDocumentRepo = $this->getMockBuilder(\project\Document\Account::class)
            ->disableOriginalConstructor()
            ->disableOriginalClone()
            ->disableArgumentCloning()
            ->disallowMockingUnknownTypes()
            ->setMethods(['remove','createQueryBuilder','field','equals','getQuery', 'execute'])
            ->getMock();

        $this->tradeDm->expects(self::any())->method('getRepository')->willReturn($accountDocumentRepo);

        $accountDocumentRepo->method('createQueryBuilder')->willReturn($accountDocumentRepo);
        $accountDocumentRepo->method('remove')->willReturn($accountDocumentRepo);
        $accountDocumentRepo->method('equals')->willReturn($accountDocumentRepo);
        $accountDocumentRepo->method('field')->willReturn($accountDocumentRepo);
        $accountDocumentRepo->method('getQuery')->willReturn($accountDocumentRepo);
        $accountDocumentRepo->method('execute')->willReturn($accountDocumentRepo);