Consider the following scenario (this is not production code):
class MyClass {
public function myMethod() {
// create a directory
$path = sys_get_temp_dir() . '/' . md5(rand());
if(!mkdir($path)) {
throw new Exception("mkdir() failed.");
}
// create a file in that folder
$myFile = fopen("$path/myFile.txt", "w");
if(!$myFile) {
throw new Exception("Cannot open file handle.");
}
}
}
Right, so what's the problem? Code coverage reports that this line is not covered:
throw new Exception("Cannot open file handle.");
Which is correct, but since I'm creating the folder above logically it would seem impossible for the fopen()
to fail (except maybe in extreme circumstances, like disk at 100 %).
I could ignore the code from code coverage but thats kind of cheating. Is there any way I can mock the file system so that it can recognise myFile.txt
and mock the file system unable to create the file?
PHPUnit provides methods that are used to automatically create objects that will replace the original object in our test. createMock($type) and getMockBuilder($type) methods are used to create mock object. The createMock method immediately returns a mock object of the specified type.
PHPUnit is a programmer-oriented testing framework for PHP. It is an instance of the xUnit architecture for unit testing frameworks. The currently supported versions are PHPUnit 9 and PHPUnit 8.
PHPUnit is a unit testing framework for the PHP programming language. It is an instance of the xUnit design for unit testing systems that began with SUnit and became popular with JUnit. Even a small software development project usually takes hours of hard work.
#3) PHPUnitIt is an open source testing tool used for PHP code. It is the most widely used framework for unit testing.
vfsStream
is a stream wrapper
for a virtual filesystem
that is useful in unit tests to mock the real filesystem. You can install it from composer.
More Info at:
https://github.com/mikey179/vfsStream
https://phpunit.de/manual/current/en/test-doubles.html
You could also break the function into 2 methods, one to create the path, and the other to use it. Then, individual tests could be done to ensure the path is created. A second set of tests could check and capture the exception when you try to use a bad path.
Yes!
You should inject the full path somehow, and don't call sys_get_temp_dir() right in that method.
Any non-existant path should trigger a problem. You don't need VFS for that.
BUT you will get a E_NOTICE (or warning perhaps?) before the exception is triggered. So you should probably first check is_writable, and throw the exception if it returns false.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With