我正在尝试使用vfsStream对文件系统交互进行单元测试,但很快就遇到了一个主要的障碍。被测代码的验证检查之一是在提供的输入路径上执行realpath(),以测试它是否为实际路径,而不是无用的。但是,realpath在vfsstream路径上总是失败。
下面的代码演示了任何特定类之外的问题。
$content = "It rubs the lotion on its skin or else it gets the hose again";
$url = vfsStream::url ('test/text.txt');
file_put_contents ($url, $content);
var_dump ($url);
var_dump (realpath ($url));
var_dump (file_get_contents ($url));输出如下:
string(27) "vfs://FileClassMap/text.txt"
bool(false)
string(61) "It rubs the lotion on its skin or else it gets the hose again"显然,vfsStream创建了该文件并将给定内容写入其中,但我无法使用realpath验证指向该文件的路径是否正确。当realpath在实际代码中被使用时,我需要一种方法来解决这个问题。
我真的不认为删除realpath是一个明智的方法,因为它在代码中执行一个重要的功能,并且消除一个重要的检查只是为了使代码可测试似乎是一个相当糟糕的解决方案。我也可以在测试过程中设置一个if,以便为了测试目的而禁用它,但我也不认为这是一个好主意。而且,我讨厌在代码中可能调用realpath ()的每一点都这样做。第三种选择是为文件系统单元测试设置一个RAM磁盘,但这也不是很理想。你必须自己清理(这是vfsstream应该帮助你避免需要的),实际如何做会因操作系统不同而不同,因此单元测试将不再与操作系统无关。
那么,有没有一种方法可以让vfsstream路径的格式能够真正与realpath一起使用呢?
为了完整起见,下面是我实际测试的类的代码片段。
if (($fullPath = realpath ($unvalidatedPath))
&& (is_file ($fullPath))
&& (is_writable ($fullPath))) {对以下内容的重构(根据潜在的解决方案2)允许我使用vfsStream进行测试,但我认为它在生产中可能会出现问题:
// If we can get a canonical path then do so (realpath can fail on URLs, stream wrappers, etc)
$fullPath = realpath ($unvalidatedPath);
if (false === $fullPath) {
$fullPath = $unvalidatedPath;
}
if ((is_file ($fullPath))
&& (is_writable ($fullPath))) {发布于 2014-03-17 05:39:11
如果使用命名空间,则只能在测试类中覆盖realpath函数。我总是在vfsStream测试用例中使用规范路径,因为我不想测试realpath()函数本身。
namespace my\namespace;
/**
* Override realpath() in current namespace for testing
*
* @param string $path the file path
*
* @return string
*/
function realpath($path)
{
return $path;
}这里描述的很好:http://www.schmengler-se.de/en/2011/03/php-mocking-built-in-functions-like-time-in-unit-tests/
发布于 2019-12-06 08:55:33
我在vfsStream上用Sebkrueger的方法实现打开了一个bug:https://github.com/bovigo/vfsStream/issues/207
等待他们的反馈,下面是我的工作realpath():
/**
* This function overrides the native realpath($url) function, removing
* all the "..", ".", "///" of an url. Contrary to the native one,
*
* @param string $url
* @param string|bool The cleaned url or false if it doesn't exist
*/
function realpath(string $url)
{
preg_match("|^(\w+://)?(/)?(.*)$|", $url, $matches);
$protocol = $matches[1];
$root = $matches[2];
$rest = $matches[3];
$split = preg_split("|/|", $rest);
$cleaned = [];
foreach ($split as $item) {
if ($item === '.' || $item === '') {
// If it's a ./ then it's nothing (just that dir) so don't add/delete anything
} elseif ($item === '..') {
// Remove the last item added since .. negates it.
$removed = array_pop($cleaned);
} else {
$cleaned[] = $item;
}
}
$cleaned = $protocol.$root.implode('/', $cleaned);
return file_exists($cleaned) ? $cleaned : false;
}https://stackoverflow.com/questions/22365519
复制相似问题