czukowski/phpunit-mock-dibi

Dibi mocking helpers for PHPUnit

4.2 2020-12-21 20:42 UTC

This package is auto-updated.

Last update: 2024-09-22 05:02:22 UTC


README

PHPUnit

一个用于数据库查询测试的模拟对象库,无需从 fixtures 初始化内存数据库。相反,测试代码执行的每个查询都可以设置为返回预定义的结果集、受影响行数或最后插入 ID。所有这些都可以使用与 PHPUnit 模拟对象相似的熟悉界面。

这是 czukowski/phpunit-mock-db 包的修改版本,用于 David Grudl 的 Dibi - PHP 的智能数据库层。Dibi 是一个数据库连接库,包含一个强大的查询构建器,支持多种关系型数据库系统。

安装

使用 Composer 安装

composer require czukowski/phpunit-mock-dibi
  • Dibi 版本 4.x 支持 PHP 7.2 或更高版本。
  • Dibi 版本 3.x 支持 PHP 5.6 或更高版本。

用法

在一个测试用例类中使用 Cz\PHPUnit\MockDibi\MockTrait 特性,这将启用创建数据库模拟实例的方法。只需调用 createDatabaseMock 方法,传递一个使用本包提供的模拟驱动之一的 Dibi\Connection 实例,并将模拟对象添加到其中并注册到测试用例类。

Cz\PHPUnit\MockDibi\Drivers\DriversFactory 中有一个方便的模拟 Dibi 驱动程序工厂类,因此您无需自己创建驱动程序实例(请参阅其源代码以获取可用的方法)。

如何创建模拟 Dibi 连接的示例

$dibi = new Dibi\Connection([
    'driver' => $factory->createMySqlDriver()  // or whatever other driver you may be needing.
]);

如何设置预期查询和模拟结果的示例

任何 数据库查询上返回预定义的结果集

$this->createDatabaseMock($dibi)
    ->expects($this->any())
    ->willReturnResultSet([
        ['id' => 1, 'name' => 'foo'],
        ['id' => 2, 'name' => 'bar'],
    ]);

任何 数据库查询上返回预定义的结果集,并期望它恰好执行一次

$this->createDatabaseMock($dibi)
    ->expects($this->once())
    ->willReturnResultSet([
        ['id' => 1, 'name' => 'foo'],
        ['id' => 2, 'name' => 'bar'],
    ]);

在每次特定数据库查询上返回预定义的结果集,期望每个查询恰好执行一次

注意:设置查询预期的顺序不必与查询执行的顺序相同。

另外注意:在查询约束中会忽略空格,因此可以从格式良好的文件中加载它们,这对于长且复杂的查询特别有用。

另外注意:不同的 Dibi 驱动程序可能使用不同的字符来引用标识符,例如 MySQL 中的反引号或 MS SQL Server 中的方括号等。查询约束将使用 Dibi Translator 转换查询,因此无需额外注意标识符引用是否匹配当前使用的驱动程序。

$mock = $this->createDatabaseMock($dibi);
$mock->expects($this->once())
    ->query('SELECT * FROM `t1`')
    ->willReturnResultSet([['id' => 1, 'name' => 'foo']]);
$mock->expects($this->once())
    ->query('SELECT * FROM `t2`')
    ->willReturnResultSet([['id' => 2, 'name' => 'bar']]);

期望混合查询,一些在特定调用中(注意:SELECT 查询设置为返回空结果集)

$mock = $this->createDatabaseMock($dibi);
$mock->expects($this->at(1))
    ->query('INSERT INTO `t1` VALUES (1, "foo")')
    ->willSetLastInsertId(1);
$mock->expects($this->at(2))
    ->query('INSERT INTO `t1` VALUES (2, "bar")')
    ->willSetLastInsertId(2);
$mock->expects($this->once())
    ->query('SELECT * FROM `t1`')
    ->willReturnResultSet([]);

期望相同的查询恰好执行三次,并在每次连续调用中返回不同的最后插入 ID

$this->createDatabaseMock($dibi)
    ->expects($this->exactly(3))
    ->query('INSERT INTO `t1` VALUES ("a", "b", "c")')
    ->willSetLastInsertId(1, 2, 3);

返回受影响行数

$this->createDatabaseMock($dibi)
    ->expects($this->exactly(2))
    ->query('UPDATE `t1` SET `foo` = "bar" WHERE `id` = 1')
    ->willSetAffectedRows(1);

使用 PHPUnit 约束匹配 SQL 查询(注意:当使用默认的 PHPUnit 约束时,将忽略空格)

$this->createDatabaseMock($dibi)
    ->expects($this->once())
    ->query($this->stringStartsWith('SELECT'))
    ->willReturnResultSet([['id' => 1, 'name' => 'foo']]);

使用连续调用存根构建器为 INSERT 查询在连续调用上设置不同的结果

$this->createDatabaseMock($dibi)
    ->expects($this->exactly(4))
    ->query($this->stringStartsWith('INSERT'))
    ->onConsecutiveCalls()
    ->willSetLastInsertId(1)
    ->willSetLastInsertId(2)
    ->willThrowException(new RuntimeException('Deadlock'))
    ->willSetLastInsertId(3);

尽管通常不需要,但可以设置自定义回调来处理数据库查询(回调不需要返回任何内容)

$mock = $this->createDatabaseMock($dibi);
$mock->expects($this->any())
    ->query($this->stringStartsWith('INSERT'))
    ->willInvokeCallback(function ($invocation) {
        $invocation->setLastInsertId(1);
    });
$mock->expects($this->any())
    ->query($this->stringStartsWith('UPDATE'))
    ->willInvokeCallback(function ($invocation) {
        $invocation->setAffectedRows(0);
    });
$mock->expects($this->any())
    ->query($this->stringStartsWith('SELECT'))
    ->willInvokeCallback(function ($invocation) {
        $invocation->setResultSet([]);
    });

默认情况下,模拟对象设置为在执行未知(不匹配)查询时抛出异常,但可以禁用此功能

$mock = $this->createDatabaseMock($dibi);
$mock->setRequireMatch(FALSE);

许可证

本作品采用MIT许可证发布。详情请参阅LICENSE.md。