@JeanPaulBelmondo

Как замокать и протестировать получение файла через fopen?

Есть такая конструкция:

spoiler

$steam = fopen($url, 'r');

while (! feof($steam)) {
    $value = json_decode(fgets($steam), true);

    // некоторый функционал
}
fclose($steam);



собственно каким образом можно замокать получение файла?
или есть какой-то другой способ протестировать данный функционал?
  • Вопрос задан
  • 107 просмотров
Пригласить эксперта
Ответы на вопрос 3
@devian3000
Можно пройтись хаком
Создать обертку над протоколом https://www.php.net/manual/en/stream.streamwrapper..., зарегестрировать этот протокол https://www.php.net/manual/ru/function.stream-wrap...

и вызов сделать что-то типо
fopen("test://file1", 'r');

должно сработать
Ответ написан
Комментировать
каким образом можно замокать получение файла?

Можно вынести чтение файла в FileReader и мокать его.
Можно ничего не мокать и для тестов держать файл-фикстуру который будет читаться исключительно тестами.
Ответ написан
Комментировать
@alvi31182v
Нужно отметить что сам fopen это ведь встроенная функция в php и мокать её напрямую достаточно сложно,
Для этого можно имплементировать типа FileReaderInterface и использовать DI.

interface FileOpenerInterface {
    public function openFile($path, $mode);
}

final class FileOpener implements  FileOpenerInterface{
public function openFile($path, $mode){
return fopen($path, $mode);
}
}

class FileProcessor{

 public function __construct(private FileOpenerInterface $fileOpener) { }

public function readFileContent($filePath) {
        $fileHandle = $this->fileOpener->openFile($filePath, 'r');
        
        if ($fileHandle) {
            $content = fread($fileHandle, filesize($filePath));
            fclose($fileHandle);
            return $content;
        } else {
            return false;
        }
    }
}

class FileProcessorTest extends PHPUnit\Framework\TestCase {

    public function testReadFileContent() {
        // Создаем мок для FileOpenerInterface
        $fileOpenerMock = $this->createMock(FileOpenerInterface::class);


        $fileOpenerMock->expects($this->once())
            ->method('openFile')
            ->willReturn(fopen('php://memory', 'r'));


        $fileProcessor = new FileProcessor($fileOpenerMock);
        $content = $fileProcessor->readFileContent('fakefile://path/to/your/file.txt');

        // Проверяем ожидаемый результат
        $this->assertEquals("", $content);
    }
}


Сам этот тест я не зпускал но для понимания думаю пойдет, там дальше уже можешь сам что нибудь накидать, прикинуть что тебе нужно и т.д
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы