我正在研究从套接字读取的一些代码,当它获得某个大输入时它会出错。在修复它之前,我去为它添加了一个单元测试,但因为我无法模拟fread
(以及我正在使用的其他PHP内置函数,如fsockopen
,{{1等等。)。
简单来说,我的问题是这段代码失败了“致命错误:无法重新声明fgets()...... ”:
feof
我意识到我可以创建一个套接字包装类,我的实际代码使用,然后我可以为该包装类创建一个模拟对象。但那就是The Tail Wagging The Dog,我可以想到这是一个坏主意的原因,而不仅仅是事物的原理。 (例如,使代码更复杂,更高效,不得不重构未经测试的代码。)
所以,我的问题是如何在单元测试中用我自己的实现替换内置的function fgets($fp){
return "xxx";
}
实现? (或者,如果你想在框外思考,那么问题可以表达为:当fgets()
是从调用的返回值时,如何控制调用fgets($socket)
的字符串返回的字符串$socket
?)
ASIDE
根据正确答案的要求安装apd是一项艰苦的工作;它最后一次发布于2004年,并不支持开箱即用的php 5.3。它没有Ubuntu包,fsockopen
也失败了。以下是安装它的过程(这些是针对ubuntu 10.04的)(全部以root身份完成):
pecl install apd
有关您需要执行的修补程序,请参阅https://bugs.php.net/bug.php?id=58798。 NB。你真的只需改变一行,所以你可以手动完成,如下所示:在文本编辑器中打开php_apd.c,转到第967行,用这一行替换pecl download apd
tar xzf apd-1.0.1.tgz
cd apd-1.0.1
phpize
./configure
# Do edits (see below)
make install
行:< / p>
CG(extended_info) = 1
最后,您需要添加一个php.ini条目来激活它。见http://php.net/manual/en/apd.installation.php
答案 0 :(得分:3)
看看这些:
bool rename_function ( string $original_name , string $new_name )
bool override_function ( string $function_name , string $function_args , string $function_code )
答案 1 :(得分:3)
如果您无权访问APD或Runkit但使用名称空间,请尝试以下操作:https://stackoverflow.com/a/5337635/664108(链接中的答案指的是时间(),但没有区别)
答案 2 :(得分:1)
将fsockopen
更改为fopen
进行模拟,不要更改任何其他功能。
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
到
$fp = fopen("/path/to/your/dummy_data_file");
答案 3 :(得分:0)
我blogged about my experiences包含完整的工作代码,显示如何使用override_function来实现所需的目标;文件读取和套接字读取。我不会在这里重复整篇文章,但只会指出你必须如何使用这些函数:
rename_function
为旧的原始函数命名,所以
我们可以在以后找到它。override_function
定义新行为rename_function
为__overridden__
如果您希望之后能够恢复原始行为,则步骤1至关重要。
在最后的Food For Thought部分中,我展示了一种我认为更强大的替代方法,因此我认为在使用phpUnit时替换文件函数更安全。它创建了一个永久性函数替换,其默认行为是转发到内置函数。然后它检查参数(在这种情况下为资源$handle
)以确定是否在我们想要不同行为的流上调用它。 (我想你可以称之为责任链设计模式的一个例子。)