是否可以在 PHP 中模拟 PECL 扩展?

Posted

技术标签:

【中文标题】是否可以在 PHP 中模拟 PECL 扩展?【英文标题】:Is it possible to mock a PECL extension in PHP? 【发布时间】:2020-05-03 18:25:16 【问题描述】:

我正在为datastax cassandra extension 开发一个包装器。

扩展的简单用法如下所示,它尝试连接到 127.0.0.1:9042 上的 Cassandra 服务器:

$connection = \Cassandra::cluster()->build()->connect(); // instance of \Cassandra\DefaultSession

显然它会出错,因为没有可用的正在运行的服务器。

我尝试逐步模拟所有这些调用,但它不起作用。 使用包mockery/mockery 的主要问题是:

\Cassandra\Cassandra\Cluster\Builder\Cassandra\DefaultSession 都定义为 final 类 所有类都已预加载,因此代理和部分模拟不起作用 我不想在我的机器上运行 cassandra 服务器,因为它无法处理如此繁重的服务器,而且我想为我正在开发的包设置 CI

知道如何处理这种情况吗?

【问题讨论】:

【参考方案1】:

您应该围绕 cassandra API 开发一个适配器,然后在测试中模拟/替换它。

【讨论】:

这样我每次都需要禁用扩展进行测试,对吧?【参考方案2】:

您可以采取一些措施来避免在测试中嘲笑整个宇宙。

在这种特定情况下,创建CassandraSessionFactory 已经足以让您更轻松地注入/模拟事物。

不过,我建议将存储库职责分离到一个接口中,并进行特定于 Cassandra 的实现。

例如,假设您有一个Person 集合/表。并且您希望您的程序能够获取它们。然后,您将使用 fetchBySomething(): Person 方法创建一个 PersonRepository 接口。稍后您将能够创建一个名为 CassandraPersonRepository 的具体实现,它使用适当的扩展来实现它。

有了上面的这个,你可以单元测试所有需要PersonRepository的东西,只需要模拟它的接口。并且仅为CassandraPersonRepository 连接进行契约测试

查看此帖子:https://thephp.website/en/issue/clean-tests-with-php-and-phpunit/ 有两个部分对您的案例有帮助:“测试不应有 I/O 操作”和“始终注入依赖项”。它们展示了实现我刚才提到的快速方法。

额外提示:使用 Prophecy 代替 phpunit 的 Mock。更容易,甚至更快。

我希望这个答案有用:)

干杯!

【讨论】:

以上是关于是否可以在 PHP 中模拟 PECL 扩展?的主要内容,如果未能解决你的问题,请参考以下文章

PHP HTTP请求

使用pecl安装php扩展时出错-bash: pecl: command not found

PECL PEAR php扩展模块的简便安装方式

用 phpize 编译共享 PECL 扩展库

在没有 PECL 扩展的 PHP5 中获取本地文件的 MIME 类型?

是否可以在不使用全局变量的 PHP 5.2.x 中模拟闭包?