jozefhornik / php-mysql-engine
用 PHP 编写的 MySQL 引擎,用于加快测试速度
Requires
- php: ^7.1|^8
- ext-pdo: *
- nyholm/dsn: ^2.0
- symfony/polyfill-php73: ^1.22
Requires (Dev)
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.5
- vimeo/psalm: ^4.6
This package is not auto-updated.
Last update: 2024-10-03 08:55:56 UTC
README
PHP MySQL 引擎是一个 PHP 库,允许您使用 MySQL 5.6 的内存模拟来测试数据库驱动应用程序。该项目扩展了 PDO
类,并允许您调用常见的 PDO MySQL 方法。它支持各种查询,以及一些 PDO 特定功能,如事务和不同的提取模式。
PHP MySQL 引擎基于 Slack 的 Hack SQL Fake,由 Scott Sandler 创建。
您可以在这里阅读有关此工具的文章。
动机
目前有两种方法可以测试读取和写入数据库的代码
-
模拟 SQL 查询执行
模拟需要显式列出预期的查询及其返回的结果。这会导致大量的手动工作来设置期望,测试脆弱且必须更新,即使在代码或查询的良性更改时也是如此。这也意味着数据访问层没有进行单元测试。 -
使用实际数据库
使用单独的数据库实例进行测试可能是有意义的——这是我们过去在 Vimeo 做过的事情。但像 MySQL 这样的数据库是为了填充大量持久数据而设计的,而单元测试写入少量非常短暂的数据。这意味着必须格外小心,确保在测试之间截断测试数据库,这会创建性能问题。
PHP MySQL 引擎采取不同的方法——它解析并执行针对存储在 PHP 数组中的内存“数据库”的 SELECT
、INSERT
、UPDATE
和 DELETE
查询。只要测试使用的数据量很小,这就可以解决上述问题。
支持的 SQL 语法
此库支持各种查询语法,包括
- 支持每个查询类型适当的
FROM
、WHERE
、GROUP BY
、HAVING
、ORDER BY
、LIMIT
子句 - 支持所有连接类型的
JOIN
查询 - 多查询,如子查询、
UNION
、UNION ALL
、INTERSECT
、EXCEPT
- 复杂的表达式,如
CASE
、BETWEEN
和行比较器(1, 2, 3) < (4, 5, 6)
- 所有基本运算符都实现了运算符优先级
- 列别名,跨数据库查询
INSERT ... ON DUPLICATE KEY UPDATE
- 各种 SQL 函数,如
COUNT(), NULLIF(), COALESCE(), CONCAT_WS()
等 - 临时变量,如
@previous_name := user.name
- 验证解析器:查询解析器将在大多数无效 SQL 查询上抛出异常,帮助保护您的生产环境免受意外的 SQL 语法错误的影响
不受支持的 MySQL 功能
此引擎不支持 MySQL 存储对象,这排除了对存储过程、触发器和视图的测试。
注意买方风险
与Psalm不同,本包并非针对广泛受众设计。若要真正从该库中受益,项目应已拥有大量需要数据库连接才能完成的测试,且项目维护者必须了解在测试套件中使用非官方MySQL实现的相关权衡。
已知问题
非模拟准备语句的结果类型
默认情况下,引擎以字符串格式返回所有数据。如果调用$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false)
,则引擎将推断列类型(例如,SUM(some_int_column)
将被赋予int
类型)。在某些情况下,与MySQL默认字符串类型不同,php-mysql-engine
可能比实际MySQL更擅长推断正确的列类型。如果您对结果进行严格的类型检查,可能会看到一些小的差异。
安装
composer require --dev vimeo/php-mysql-engine
用法
PHP MySQL Engine通过提供PDO的子类来工作。
您可以像使用PDO
一样实例化子类,并通过依赖注入或类似方法将其实例提供给您的应用程序代码。
// use a class specific to your current PHP version (APIs changed in major versions) $pdo = new \Vimeo\MysqlEngine\Php8\FakePdo($dsn, $user, $password); // currently supported attributes $pdo->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_LOWER); $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
其余的代码可以按正常方式运行,以与生产环境中相同的方式使用数据库。
为什么不支持X?
本库旨在支持用户在MySQL中使用的一切,而不是MySQL提供的所有可能的功能。我们欢迎提交拉取请求以添加对新语法的支持、sql函数、数据类型、错误修复和其他功能。
为什么该项目没有问题跟踪器?
维护开源项目是一项艰巨的任务,我不想给自己或我的同事增加更多工作量。请自行承担使用此项目的风险。
如果您想使用问题跟踪器分叉项目,请随意!
贡献
如果您想创建一个PR,请确保它通过单元测试
vendor/bin/phpunit
以及Phasmal的检查
vendor/bin/psalm
谢谢!