我正在为我的核心库更新单元测试,并遇到了关于文件锁(flock)的场景,并希望了解其他人如何实现这些类型的单元测试。
基本上我有一个可以将内容写入文件的文件类:
class CoreLib_Api_File_Package
{
public static function write(array $options)
{
...
if (!$file->flock(LOCK_EX)) {
throw new CoreLib_Api_Exception('Unable to obtain lock on file');
}
...
}
}
我的单元测试看起来像:
public function testWriteException_UnableToSecureLock()
{
$this->touchFile($this->destFileUri);
$file = new SplFileObject($this->destFileUri, CoreLib_Api_File::MODE_WRITE);
$file->flock(LOCK_EX);
CoreLib_Api_File_Package::write(array('fileUri' => $this->destFileUri, 'content' => $this->testContent, 'mode' => CoreLib_Api_File::MODE_WRITE));
}
从测试代码中可以看出,在对$this->destFileUri
方法进行API调用之前,我在write()
上显式锁定了。我期望的是抛出异常throw new CoreLib_Api_Exception('Unable to obtain lock on file');
。相反,我的单元测试只是无限期挂起。
测试文件是否有锁的正确方法是什么?
提前致谢。
答案 0 :(得分:3)
您应该检查flock
this comment上的docs page。
基本上,flock
将暂停执行,直到它能够获得锁定。请使用以下代码,与上述情况类似:
$file = 'file.txt';
$first = fopen($file, "w");
flock($first, LOCK_EX);
$second = fopen($file, "w");
# Your script will pause on the next line until timeout
# due to the inability to obtain a lock.
flock($second, LOCK_EX);
但是,您可以获得如下的非阻塞锁:
flock($file, LOCK_EX | LOCK_NB);
我不确定以这种方式锁定文件是否会产生负面影响。此外,虽然文档说LOCK_NB
在Windows上不起作用,但我只测试了它并且它在我的机器上运行。因此,您可以在CoreLib_Api_File_Package::write
方法中执行以下操作:
class CoreLib_Api_File_Package
{
public static function write(array $options)
{
if ( ! $file->flock(LOCK_EX | LOCK_NB))
{
throw new CoreLib_Api_Exception('Unable to obtain lock on file');
}
}
}
您当前的测试应按原样通过。除此之外,我什么都想不到。
修改:只要您告诉PHPUnit
期待CoreLib_Api_Exception
异常(仅指出它,因为您的示例中没有它),它们就应该通过)。