1

我正在处理一些从套接字读取的代码,当它获得一定的大输入时会出错。在修复它之前,我为此添加了一个单元测试,但是因为我无法模拟fread(以及我正在使用的其他 PHP 内置函数,例如fsockopen,feof等)而被卡住了。

简单来说,我的问题是此代码因“致命错误:无法重新声明 fgets() ... ”而失败:

function fgets($fp){
return "xxx";
}

我意识到我可以创建一个套接字包装类,我的真实代码使用它,然后我可以为该包装类创建一个模拟对象。但这就是《摇尾巴》,我能想到原因,这是一个坏主意,不仅仅是事情的原理。(例如,使代码更复杂、更高效,必须重构尚未测试的代码。)

fgets()所以,我的问题是如何在单元测试中用我自己的替换内置实现?(或者,如果您想跳出框框思考,问题可以表述为:如何控制调用返回的字符串,调用fgets($socket)$socket返回值是什么时候fsockopen?)


在旁边

按照正确答案的要求安装 apd 是一项艰苦的工作;它最后一次发布是在 2004 年,并且不支持开箱即用的 php 5.3。没有适用于它的 Ubuntu 软件包,也pecl install apd失败了。所以这里是安装它的过程(这些是针对 ubuntu 10.04)(都是以 root 身份完成的):

pecl download apd
tar xzf apd-1.0.1.tgz
cd apd-1.0.1
phpize
./configure
# Do edits (see below)
make install

有关您需要做的补丁,请参阅https://bugs.php.net/bug.php?id=58798 。注意。只有一行您真正需要更改,因此您可以手动更改,如下所示:在文本编辑器中打开 php_apd.c,转到第 967 行,并将该CG(extended_info) = 1行替换为这一行:

CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;

最后,您需要添加一个 php.ini 条目来激活它。见http://php.net/manual/en/apd.installation.php

4

4 回答 4

3

如果您无权访问 APD 或 Runkit 但正在使用命名空间,请尝试以下操作:https ://stackoverflow.com/a/5337635/664108 (链接中的答案是指 time() 但没有区别)

于 2012-07-05T09:09:18.077 回答
1

fsockopen改为fopen做模拟,不要改变任何其他功能。

$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);

$fp = fopen("/path/to/your/dummy_data_file");
于 2012-07-01T08:19:34.683 回答
0

写了一篇关于我的经历的博客,其中包含完整的工作代码,展示了如何使用 override_function 来实现预期的目标;文件读取和套接字读取。我不会在这里重复整篇文章,而只会指出您必须如何使用这些功能:

  1. 用于rename_function为旧的原始函数命名,以便我们稍后找到它。
  2. 用于override_function定义新行为
  3. rename_function用来给一个假名__overridden__

如果您希望之后能够恢复原始行为,那么第 1 步至关重要。

在最后的思考部分,我展示了一种我认为更强大的替代方法,因此我认为在使用 phpUnit 时替换文件函数更安全。它创建了一个永久函数替换,其默认行为是转发到内置函数。然后它检查参数($handle在这种情况下是资源)来决定是否在我们想要不同行为的流上调用它。(我认为您可以将其称为责任链设计模式的示例。)

于 2012-07-02T02:48:27.663 回答