Issue
Short version: For unit testing, I need an unreadable file to make sure the correct exception is thrown. Obviously, that unreadable file can't be stored by Git, so I chmod 000
at testing time and use git update-index --assume-unchanged
so that Git doesn't try storing the unreadable file. But then I can't checkout a different branch, but get the error "Your local changes to the following files would be overwritten by checkout."
Is there a better way to test, OR a better way to use Git so that everything plays nicely?
Long version: In one class, I have a method to read a file so that its contents can be imported into a database:
public function readFile($path) {
...
if(!is_readable($path))
throw new FileNotReadableException("The file $path is not readable");
...
}
I test that method using PHPUnit, and one test in particular should (indirectly) trigger the 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__);
}
After a test, git checkout other_branch
will abort:
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
Solution
You have a couple of options.
Add a tearDown()
method to the test that resets the file permissions so that git does not think that the file was modified. Then even if the test fails the file will be reset.
http://phpunit.de/manual/current/en/fixtures.html
public function tearDown() {
@chmod(__DIR__ . $file, 0755); //Whatever the old permissions were;
}
If you are using PHP 5.3+, you can use name-spacing and mock the is_readable
function. In your test file, override is_readable
with your own function. You will need to make sure that your override is in the same namespace as your class that you are testing.
http://www.schmengler-se.de/-php-mocking-built-in-functions-like-time-in-unit-tests
In your class you would do this:
namespace SUT
class SUT {
public function readFile($path) {
...
if(!is_readable($path))
throw new FileNotReadableException("The file $path is not readable");
...
}
}
Then in your test you do the following:
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);
}
}
You would then not even have to include the files in your repo or worry about the permissions on it.
Answered By - Schleis Answer Checked By - Marie Seifert (WPSolving Admin)