michaelmoussa / doctrine-qbmocker
用于模拟 Doctrine 查询构建器的辅助库
Requires
- php: ^7.0.0
- phpunit/phpunit: ^6.0.0
Requires (Dev)
- alcaeus/mongo-php-adapter: ^1.0
- doctrine/mongodb: ^1.4
- doctrine/mongodb-odm: ^1.1
- doctrine/orm: ^2.5
- jmikola/geojson: ^1.0
- satooshi/php-coveralls: ^0.6.1
- squizlabs/php_codesniffer: ^2.3
Suggests
- doctrine/mongodb-odm: Allows for simplified mocking of Doctrine ODM MongoDB query builders.
- doctrine/orm: Allows for simplified mocking of Doctrine ORM query builders.
- jmikola/geojson: Required for doctrine/mongodb-odm.
README
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();
}
这很简单。现在我们如何测试它呢?
我们可以创建一个测试数据库,添加一些测试记录,然后运行该方法以查看是否检索到正确的数据,但这不是最佳方案。
- 在测试中连接到数据库相对较慢。在测试套件中包含太多此类测试会使测试套件运行缓慢。
- 它只测试你是否获取了预期的数据 - 并没有测试你的方法是否正确检索数据。
- 如果有人意外删除了
->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%的测试覆盖率。