3

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

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

提前致谢。

4

1 回答 1

3

您应该在文档页面上查看此评论flock

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

于 2012-02-03T23:02:03.917 回答