如何在 Symfony 中为使用 queryBuilder 构建的 MongoDB 查询编写单元测试
Posted
技术标签:
【中文标题】如何在 Symfony 中为使用 queryBuilder 构建的 MongoDB 查询编写单元测试【英文标题】:How to write a unit test for MongoDB query built with queryBuilder in Symfony 【发布时间】:2022-01-16 01:36:04 【问题描述】:我很难理解如何为这段代码编写单元测试
$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 单元:PHPUnit 8.5.21
PHP:PHP 7.2.34
Symfony:Symfony 4.4.18
【问题讨论】:
【参考方案1】:出现错误是因为你没有从$documentManager
模拟,你的测试用例显然必须从它开始。
我曾经使用Prophecy
进行测试,但使用原生MockBuilder
是相同的逻辑。
考虑到我不知道你的用例使用的真实类,所以我让你大致了解你必须做什么,看看下面的代码:
$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();
【讨论】:
对不起,我忘了提到$documentManager
已通过测试为$this->dm
您在声明后没有在任何地方使用$documentManager
。其次,您的意思是 $queryBuilder = $this->createMock(documentAccount::class);
吗?当你说$queryBuilder = $this->createMock(QueryBuilder::class);
documentAccount 是Document:Account
谢谢
我编辑解决方案,因为我忘记了 $documentManager,
方法 ->createQueryBuilder()
的模拟,你必须检查什么是建立相应模拟的真正类,我不认为它是 documentAccount
,不要不要忘记这是一个提案,因为我不知道你的全部代码。【参考方案2】:
这是我修复它的方法。这可能对遇到类似问题的人有所帮助
$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);
【讨论】:
正如我在回答中提到的,您需要模拟所有调用的方法。以上是关于如何在 Symfony 中为使用 queryBuilder 构建的 MongoDB 查询编写单元测试的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 LoginFormAuthenticator 和 Login Link Authenticator 在 Symfony 5.2 中为特定路径设置默认身份验证器