Как в тестах сделать mock статичного метода в yii2?

В тестируемом методе вызывается статичный метод другого класса (FileHelper::createDirectory($path);).
Как в yii2 сделать mock этого метода?

protected function _generateFolders()
    {
        $folders = str_split($this->hash, self::FOLDER_TITLE_LENGTH);
        $folders = array_slice($folders, 0, $this->foldersDepth);
        $folders = implode('/', $folders) .
            ($this->accessDir ? '/' . $this->accessDir : '');

        $path = self::getPathToFiles() . '/' . $folders;
        FileHelper::createDirectory($path);

        return $folders;
    }


Просто статичные методы можно подменить с помощью https://github.com/Codeception/AspectMock
Но в yii он как-то глючит..
  • Вопрос задан
  • 1157 просмотров
Пригласить эксперта
Ответы на вопрос 3
He11ion
@He11ion
PHP-monkey
В phpunit - никак.
Ответ написан
Denormalization
@Denormalization
Посмотрел в код Yii, оказывается они действительно используют статик методы для хелперов...

Не пишу на Yii, но могу посоветовать отказаться от прямого использования их статичных классов, и работать через свою обертку.

Т.е сделать класс MySuperHelpers, в который инкапсулировать всю работу со статикой, и уже свой класс использовать везде. Т.е:
<?php

class MyHelpers {

	public function makeDirectory($path)
	{
		return FileHelper::createDirectory($path);
	}

}


А свой класс уже можно без проблем мокать где нужно.
Ответ написан
@matperez
Кстати, еще вариант. Если у вас в классе есть метод, который использует статику или, допустим, должен обращаться к файловой системе, что вам не хочется делать в тестах, можно явно вынести эту функциональность в отдельный приватный метод и его уже замокать. Получится что-то вроде
class Actor
{
    public function generateFolders()
    {
        $folders = str_split($this->hash, self::FOLDER_TITLE_LENGTH);
        $folders = array_slice($folders, 0, $this->foldersDepth);
        $folders = implode('/', $folders) .
            ($this->accessDir ? '/' . $this->accessDir : '');

        $path = self::getPathToFiles() . '/' . $folders;
        $this->createDirectory($path);
        return $folders;
    }
    
    protected function createDirectory($path)
    {
        return  FileHelper::createDirectory($path);
    }
}


В этом коде уже довольно легко замокать явное обращение к статическому методу. Остальные методы при этом будут работать как обычно.
$actor = $this->getMock('Actor', ['createDirectory']);
        $actor->expects($this->any())->method('createDirectory')->willReturn(true);


Это проще чем реализовывать полноценный DI с подменой реализации интерфейсов.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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