请考虑以下方案(这不是生产代码):
class MyClass {
public function myMethod() {
// create a directory
$path = sys_get_temp_dir() . '/' . md5(rand());
if(!mkdir($path)) {
throw new Exception("mkdir() failed.");
}
// create a file in that folder
$myFile = fopen("$path/myFile.txt", "w");
if(!$myFile) {
throw new Exception("Cannot open file handle.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
对,那有什么问题?代码覆盖率报告此行未涵盖:
throw new Exception("Cannot open file handle.");
Run Code Online (Sandbox Code Playgroud)
哪个是正确的,但是因为我在逻辑上创建了上面的文件夹,所以fopen()失败似乎是不可能的(除非在极端情况下,例如100%的磁盘).
我可以忽略代码覆盖中的代码但这有点作弊.有什么方法可以模拟文件系统,以便它可以识别myFile.txt和模拟无法创建文件的文件系统?
我正在尝试使用vfsStream来模拟文件系统操作(实际上是从php://输入读取),但缺乏体面的文档和示例实际上是在妨碍我.
我正在测试的类中的相关代码如下:
class RequestBody implements iface\request\RequestBody
{
const
REQ_PATH = 'php://input',
protected
$requestHandle = false;
/**
* Obtain a handle to the request body
*
* @return resource a file pointer resource on success, or <b>FALSE</b> on error.
*/
protected function getHandle ()
{
if (empty ($this -> requestHandle))
{
$this -> requestHandle = fopen (static::REQ_PATH, 'rb');
}
return $this -> requestHandle;
}
}
Run Code Online (Sandbox Code Playgroud)
我在PHPUnit测试中使用的设置如下:
protected function configureMock ()
{
$mock = $this -> getMockBuilder ('\gordian\reefknot\http\request\RequestBody');
$mock -> setConstructorArgs (array …Run Code Online (Sandbox Code Playgroud) 我想使用 vfsstream
class MyClass{
public function createFile($dirPath)
{
$name = time() . "-RT";
$file = $dirPath . '/' . $name . '.tmp';
fopen($file, "w+");
if (file_exists($file)) {
return $name . '.tmp';
} else {
return '';
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试测试文件创建时:
$filename = $myClass->createFile(vfsStream::url('/var/www/app/web/exported/folder'));
Run Code Online (Sandbox Code Playgroud)
我收到一个错误:
无法打开流:“org\bovigo\vfs\vfsStreamWrapper::stream_open”调用失败 fopen(vfs://var/www/app/web/exported/folder)
我看到这个问题在谈论模拟文件系统,但它没有关于文件创建的信息。vfsstream 是否支持使用 fopen 函数创建文件?如何测试文件创建?
我正在尝试使用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));
Run Code Online (Sandbox Code Playgroud)
输出如下:
string(27) "vfs://FileClassMap/text.txt"
bool(false)
string(61) "It rubs the lotion on its skin or else it gets the hose again"
Run Code Online (Sandbox Code Playgroud)
显然,vfsStream创建了文件并将给定内容写入其中,但我无法验证它的路径是否与realpath一致.由于在实际代码中使用了realpath,我需要一种解决方法.
我真的不认为删除realpath是一种明智的方法,因为它在代码中执行一个重要的功能,并且消除一个重要的检查只是为了使代码可测试似乎是一个非常糟糕的解决方案.我还可以在测试周围放置一个if来使其可以禁用它用于测试目的,但我不认为这也是一个好主意.此外,我不想在代码中的每一点都这样做,我可能会调用realpath().第三种选择是为文件系统单元测试设置RAM磁盘,但这也不理想.您必须自己清理(这是vfsstream应该帮助您避免的必要)以及如何实际执行它将因操作系统而异,因此单元测试将不再与操作系统无关.
那么有没有办法以实际使用realpath的格式获取vfsstream路径?
为了完整起见,以下是我正在尝试实际测试的类中的代码片段.
if (($fullPath = realpath ($unvalidatedPath))
&& (is_file ($fullPath))
&& (is_writable ($fullPath))) {
Run Code Online (Sandbox Code Playgroud)
对以下内容进行重构(根据潜在的解决方案2)允许我使用vfsStream进行测试,但我认为它在生产中可能存在问题:
// If we can get a canonical path then do so …Run Code Online (Sandbox Code Playgroud)