gpt4 book ai didi

php - 为什么 Memcache::get() 的反射与文档不同?

转载 作者:行者123 更新时间:2023-12-04 03:21:59 25 4
gpt4 key购买 nike

我正在尝试将单元测试添加到一个使用 Memcache 作为服务以在本地 memcached 守护程序上获取和存储 key 的类。

我的问题是,尽管代码运行良好,但当我尝试模拟 Memcache 类并调用 get() 方法时,我得到了这种错误:

ArgumentCountError: Too few arguments to function Mock_Memcache_b25e34cb::get(), 1 passed in /path/to/file.php on line 64 and exactly 3 expected

我怀疑是反射错误,所以我尝试了一个小脚本来测试它:

<?php
$class = new ReflectionClass(Memcache::class);
$getMethod = $class->getMethod('get');
$getParams = $getMethod->getParameters();
foreach($getParams as $param) {
var_dump((string) $param);
}

我得到的输出是

string(35) "Parameter #0 [ $param0 ]"

string(36) "Parameter #1 [ &$param1 ]"

string(36) "Parameter #2 [ &$param2 ]"

但是,在 the official PHP doc 找到的文档指出签名应该是:

Memcache::get(string $key, int &$flags = ?): string

Memcache::get(array $keys, array &$flags = ?): array

如何解释差异?为什么我的代码在生产环境中运行良好,但在 UT 环境中却失败了?除了为 Memcache 创建我自己的模拟类之外,有没有办法解决这个问题?谢谢!

仅供引用,我目前获取模拟的方法是这样的:

protected function createMock($originalClassName)
{
return $this->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->disallowMockingUnknownTypes()
->getMock();
}

public function existsReturnsTrueOrFalse($value, $expected)
{
$memcacheMock = $this->createMock(\Memcache::class);
...
}

最佳答案

How can the discrepancy be explained?

大多数情况下,这只是扩展的文档不是最新的。

另一种解释可能是库反射错误。

看到反射的输出,我会说文档比反射更新。

Why does my code run fine on production but fails on the UT?

您的问题的单元测试的生产和测试运行之间的区别在于模拟的创建:在生产中您不创建模拟,因此它不会失败。

Is there a way for me to solve this problem other than creating my own mock class for Memcache?

实际上,创建您自己的模拟类听起来并不是一个坏主意。但是,您可能会考虑更进一步:

现在生产代码将 Memcache 类作为依赖项。您的测试已经向您表明,它的接口(interface)不稳定,依赖项拒绝测试(使用您的标准工具,如模拟)。

出于诸如此类的原因,通常建议包装第三方库。这可能是一个边缘案例,因为这与可能不太易变的 PHP 扩展相关,但包装可能已经为您提供了更多的开发、测试和维护空间。

您可以将您使用的 Memcache 类的公共(public)接口(interface)部分提取到接口(interface)本身中,例如内存缓存接口(interface)。然后,您可以创建一个实现接口(interface)的轻量级包装类,并在后台将方法调用委托(delegate)给 Memcache 实例。

然后,您将生产代码中的 Memcache 对象替换为您的包装器对象,并将 Memcache 的类型提示替换为您的 MemcacheInterface 接口(interface).

在测试中,您从界面创建模拟。

这将

  1. 记录每个使用的方法和参数(您在界面上执行此操作)。
  2. 允许在 Phpunit 中创建模拟,就像您从(明确的)界面创建模拟一样。
  3. 通过新的包装类在中央位置访问第三方库的接口(interface) - 即使在生产中也是如此。
  4. 允许您将来在您的应用程序中切换到不同的 memcache 第三方库(但您不能,我为了简洁而提到它)。

关于php - 为什么 Memcache::get() 的反射与文档不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68348357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com