michaelmoussa/doctrine-qbmocker

此包已废弃,不再维护。未建议替代包。

用于模拟 Doctrine 查询构建器的辅助库

1.0.0 2017-04-08 02:29 UTC

This package is not auto-updated.

Last update: 2023-12-09 10:14:59 UTC


README

Build Status Coverage Status Latest Stable Version

Doctrine QueryBuilderMocker

这是什么?

一个工具,用于轻松模拟 Doctrine QueryBuilder 对象,以方便单元测试。

示例

假设你有一个看起来像这样的用户账户集合

{
    firstName: "John",
    lastName: "Doe",
    email: "JohnDoe@example.com",
    country: "USA"
}

你有一个名为 User 的服务类,其中有一个方法返回特定国家的所有用户名称和电子邮件地址,按姓氏、名字排序

public function getUsersByCountry($country)
{
    return $this->documentManager->createQueryBuilder('My\Document\User')
                                 ->select('firstName', 'lastName', 'email')
                                 ->field('country')->equals($country)
                                 ->sort('lastName', 'firstName')
                                 ->getQuery()
                                 ->execute();
}

这很简单。现在我们如何测试它呢?

我们可以创建一个测试数据库,添加一些测试记录,然后运行该方法以查看是否检索到正确的数据,但这不是最佳方案。

  1. 在测试中连接到数据库相对较慢。在测试套件中包含太多此类测试会使测试套件运行缓慢。
  2. 它只测试你是否获取了预期的数据 - 并没有测试你的方法是否正确检索数据。
    • 如果有人意外删除了 ->field('country')->equals($country)?或将它改为 ->gte($country)?或删除了 ->sort('lastName', 'firstName')
    • 根据你创建的测试记录及其创建顺序,即使你的方法没有以你期望的方式检索数据,你也可能仍然得到预期的结果。你的测试仍然会通过,但代码是错误的。

更好的测试方法是模拟预期的方法调用,并确保查询构建器被正确使用。

但最终结果却相当混乱...看看这个

public function testCanGetSortedUsersByCountry()
{
    $mockQuery = $this->getMockBuilder('Doctrine\ODM\MongoDB\Query\Builder')
                      ->disableOriginalConstructor()
                      ->getMock();
    $mockQuery->expects($this->once())
              ->method('execute')
              ->will($this->returnValue('it works!'));
    
    $mockQueryBuilder = $this->getMockBuilder('Doctrine\ODM\MongoDB\Query\Builder')
                             ->disableOriginalConstructor()
                             ->getMock();
    $mockQueryBuilder->expects($this->at(0))
                     ->method('select')
                     ->with('firstName', 'lastName', 'email')
                     ->will($this->returnValue($mockQueryBuilder));
    $mockQueryBuilder->expects($this->at(1))
                     ->method('field')
                     ->with('country')
                     ->will($this->returnValue($mockQueryBuilder));
    $mockQueryBuilder->expects($this->at(2))
                     ->method('equals')
                     ->with('USA')
                     ->will($this->returnValue($mockQueryBuilder));
    $mockQueryBuilder->expects($this->at(3))
                     ->method('sort')
                     ->with('lastName', 'firstName')
                     ->will($this->returnValue($mockQueryBuilder));
    $mockQueryBuilder->expects($this->at(4))
                     ->method('getQuery')
                     ->will($this->returnValue($mockQuery));
    
    $mockDocumentManager = $this->getMockBuilder('Doctrine\ODM\MongoDB\DocumentManager')
                                ->disableOriginalConstructor()
                                ->getMock();
    $mockDocumentManager->expects($this->once())
                        ->method('createQueryBuilder')
                        ->with('My\Document\User')
                        ->will($this->returnValue($mockQueryBuilder));
    
    $service->setDocumentManager($mockDocumentManager);
    
    $this->assertSame('it works!', $this->service->getUsersByCountry('USA'));

想象一下一个单元测试类中充满了这些!当然我们可以做得更好。看看这个?

public function testCanGetSortedUsersByCountry()
{
    $qbm = new QueryBuilderMocker($this);
    $qbm->select('firstName', 'lastName', 'email')
        ->field('country')->equals($country)
        ->sort('lastName', 'firstName')
        ->getQuery()
        ->execute('it works!');
    $qb = $qbm->getQueryBuilderMock();
    
    $this->assertSame('it works!', $this->service->getUsersByCountry('USA'));
}

简短而简洁!注意,它与实际服务类中进行的调用几乎相同:唯一的区别是 execute() 接受一个参数,该参数最终成为模拟的 execute() 调用的值。模拟方法对查询构建器的使用(或反之,对于那些做TDD的人来说)就像复制粘贴一样简单。

更喜欢 MySQL?此库还支持模拟 Doctrine ORM 查询构建器。只需使用 MMoussa\Doctrine\Test\ORM\QueryBuilderMocker 而不是 MMoussa\Doctrine\Test\ODM\MongoDB\QueryBuilderMocker 即可!

安装

唯一支持的安装方法是 Composer: composer require --dev "michaelmoussa/doctrine-qbmocker"

依赖

  • 使用此库模拟 ORM 查询构建器需要您也执行 composer require --dev "doctrine/orm"
  • 使用此库模拟 ODM 查询构建器需要您也执行 composer require --dev "doctrine/mongodb-odm" "jmikola/geojson"

PHPUnit 支持

  • 版本 1.0 中添加了对 PHPUnit 6 的支持
  • 版本 0.x 支持旧版本的 PHPUnit

贡献

我已经不再积极维护这个项目,但我还是会审查和合并Pull Requests,所以欢迎贡献。还有一些不受支持的方法仍然存在,实现起来可能相当复杂。请随时处理这些并提交Pull Request。

所有贡献必须符合PSR2规范,并包含100%的测试覆盖率。