PHP - PHPUnit - 测试保护文件锁的能力

时间:2012-02-03 22:14:34

标签: php phpunit flock

我正在为我的核心库更新单元测试,并遇到了关于文件锁(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');。相反,我的单元测试只是无限期挂起。

测试文件是否有锁的正确方法是什么?

提前致谢。

1 个答案:

答案 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异常(仅指出它,因为您的示例中没有它),它们就应该通过)。