PHPUnit和Git:如何使用不可读的文件进行测试?

jch*_*ain 6 php git phpunit chmod

简短版本:对于单元测试,我需要一个不可读的文件来确保抛出正确的异常.显然,Git无法存储该无法读取的文件,因此我chmod 000在测试时使用,git update-index --assume-unchanged以便Git不会尝试存储不可读的文件.但后来我无法签出一个不同的分支,但得到错误"您对以下文件的本地更改将被结帐覆盖."

有没有更好的测试方法,或者更好的方式来使用Git,以便一切运行良好?

长版本:在一个类中,我有一个方法来读取文件,以便将其内容导入到数据库中:

public function readFile($path) {
    ...
    if(!is_readable($path))
      throw new FileNotReadableException("The file $path is not readable");
    ...
  }
Run Code Online (Sandbox Code Playgroud)

我使用PHPUnit测试该方法,特别是一个测试应该(间接)触发FileNotReadableException:

/**
 * @expectedException Data\Exceptions\FileNotReadableException
 */
public function testFileNotReadableException() {
  $file = '/_files/6504/58/6332_unreadable.xlsx';
  @chmod(__DIR__ . $file, 0000);
  $import = Import::find(58);
  $import->importFile(array('ID'=>2, 'newFilename'=> $file), __DIR__);
}
Run Code Online (Sandbox Code Playgroud)

经过测试,git checkout other_branch将中止:

error: Your local changes to the following files would be overwritten by checkout:
    Data/Tests/_files/6504/58/6332_unreadable.xlsx
Please, commit your changes or stash them before you can switch branches.
Aborting
Run Code Online (Sandbox Code Playgroud)

Sch*_*eis 6

你有几个选择.

tearDown()在测试中添加一个重置文件权限的方法,以便git不会认为该文件已被修改.然后即使测试失败,文件也会被重置.

http://phpunit.de/manual/current/en/fixtures.html

public function tearDown() {
     @chmod(__DIR__ . $file, 0755); //Whatever the old permissions were;
}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是PHP 5.3+,则可以使用名称间距并模拟该is_readable函数.在您的测试文件中,is_readable使用您自己的函数覆盖.您需要确保覆盖与您正在测试的类位于同一名称空间中.

http://www.schmengler-se.de/-php-mocking-built-in-functions-like-time-in-unit-tests

在你的班上你会这样做:

namespace SUT

class SUT {
    public function readFile($path) {
        ...
        if(!is_readable($path))
          throw new FileNotReadableException("The file $path is not readable");
        ...
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在测试中执行以下操作:

namespace SUT

function is_readable($filename) {
    if (str_pos('unreadable') !== FALSE)) {
        return false;
    }

    return true;
}

class SUTTest extends PHPUNIT_Framework_TestCase {
    /**
     * @expectedException Data\Exceptions\FileNotReadableException
     */
     public function testFileNotReadableException() {
        $file = '/_files/6504/58/6332_unreadable.xlsx';
        $sut = new SUT();
        $sut->readFile($file);
     }
}
Run Code Online (Sandbox Code Playgroud)

然后,您甚至不必将文件包含在您的仓库中或担心其权限.