PHP Framework для создания насмешливого кода


Введение

Этот класс предоставляет абстракции от основных инфраструктурных вещей, которые могут усложнить юнит-тестирование. Например:

  • вывод консоли
  • операции с файловой системой
  • библиотека GD
  • перенаправления
  • сеансы
  • системные методы

Если вы будете писать свой код, используя этот фреймворк, то ваши юнит-тесты будет намного проще писать и поддерживать. И как следствие — ваш код будет более стабильным.

Основные концепции

Каждая абстракция может быть настроена на использование либо собственных вызовов функций (например, file_get_contents), либо макетов.

Макетные вызовы могут использоваться в ваших модульных тестах. А нативные вызовы будут выполняться в продакшене.

Давайте посмотрим несколько примеров реального кода:

// here we setup mock calls
MezonConfConf::setConfigStringValue('fs/layer', 'mock');

// here we setup that mock will return true if the we check that this directory exists
MezonFsLayer::$createdDirectories[] = [
    'path' => 'path-to-existing-directory'
];

// here we will get true
var_dump(MezonFsLayer::directoryExists('path-to-existing-directory'));

// and here we will get false
var_dump(MezonFsLayer::directoryExists('path-to-unexisting-directory'));
Вход в полноэкранный режим Выход из полноэкранного режима

В обоих вызовах MezonFsLayer::directoryExists не было реального вызова метода file_exists.

Нет, давайте посмотрим, какие абстракции у нас есть

Консольный слой

Класс MezonConsoleLayer предоставляет абстракции для работы с winth консолью

// here we setup mock calls
Conf::setConfigStringValue('console/layer', 'mock');

// setup values wich will be returned by the method MezonConsoleLayer::readline()
MezonConsoleLayer::$readlines[] = 'line 1';
MezonConsoleLayer::$readlines[] = 'line 2';

// read lines
// note that native php method `readline` will noe be called
// just returning value of the MezonConsoleLayer::$readlines array
echo MezonConsoleLayer::readline(); // ouputs 'line 1'
echo MezonConsoleLayer::readline(); // ouputs 'line 2'

// here we setup native php methods calls
Conf::setConfigStringValue('console/layer', 'real');
echo MezonConsoleLayer::readline(); // outputs string wich you will input in the console
// because in this line real method `readline` will be called
Вход в полноэкранный режим Выход из полноэкранного режима

Уровень файловой системы

Этот пакет также содержит абстракции для работы с файловыми системами:

// here we setup mock calls
Conf::setConfigStringValue('fs/layer', 'mock');

// writing file
MezonFsLayer::filePutContents('file-path', 'data', FILE_APPEND);
// ^^^ but in this call all file content will be stored into memory, not on disk
// on production this call works like file_put_contents

// creating directory
MezonFsLayer::createDirectory('new-dir');
// ^^^ real directory also is not created

// checking if the directory exists
echo MezonFsLayer::directoryExists('new-dir'); // we shall see 'true', because we have called MezonFsLayer::createDirectory('new-dir');
echo MezonFsLayer::directoryExists('unexisting-dir'); // we shall see 'false'

// checking if the file exists
echo MezonFsLayer::fileExists('file-path'); // we shall see 'true', because we have called MezonFsLayer::filePutContents('file-path', 'data', FILE_APPEND)
echo MezonFsLayer::fileExists('unexisting-file-path'); // we shall see 'false'

// getting file contents
echo MezonFsLayer::fileGutContents('file-path'); // we shall see 'data', because we have already called MezonFsLayer::filePutContents('file-path', 'data', FILE_APPEND)
echo MezonFsLayer::fileGutContents('unexisting-file-path'); // we shall see 'false'
Вход в полноэкранный режим Выход из полноэкранного режима

Файловая система в памяти

Почти все методы из MezonFsLayer в режиме mock используют MezonFsInMemory.

// writing data in memory file system
MezonFsInMemory::filePutContents('file-path', 'data');

// reading data from inmemory file system
echo MezonFsInMemory::fileGetContents('file-path');

// checking that file esists
echo MezonFsInMemory::fileExists('file-path'); // outputs 'true'
echo MezonFsInMemory::fileExists('unexisting-file'); // outputs 'false'

// preload file in FS
// this method reads real file from your FS and uploads it into inmemory FS
MezonFsInMemory::preloadFile('real-file-path');
Вход в полноэкранный режим Выход из полноэкранного режима

Макеты GD

У нас также есть макеты для некоторых функций GD. В основном для тех, которые работают с файловой системой.

Conf::setConfigStringValue('gd/layer', 'mock');
// here we are trying to get file with this path from MezonFSInMemory
var_dump(MezonGDLayer::getImageSize('path-to-image'));

// reading image from file
$resource = MezonGDLayer::imageCreateFromBmp('path-to-image-file');
$resource = MezonGDLayer::imageCreateFromGif('path-to-image-file');
$resource = MezonGDLayer::imageCreateFromJpeg('path-to-image-file');
$resource = MezonGDLayer::imageCreateFromPng('path-to-image-file');
$resource = MezonGDLayer::imageCreateFromWebp('path-to-image-file');

// store images into file. In mock mode all data is stored into in-memory FS - MezonFSInMemory
MezonGDLayer::imageBmp($resource, 'path-to-file');
MezonGDLayer::imageGif($resource, 'path-to-file');
MezonGDLayer::imageJpeg($resource, 'path-to-file');
MezonGDLayer::imagePng($resource, 'path-to-file');
MezonGDLayer::imageWebp($resource, 'path-to-file');
Вход в полноэкранный режим Выход из полноэкранного режима

Инсценировки перенаправления

Вы можете имитировать перенаправления:

Conf::setConfigStringValue('redirect/layer', 'mock');

// in real mode this call method header('Location: ...') will be called
// in mock mode no redirection will be performed and redirect URL will be stored
// in the MezonRedirectLayer::$lastRedirectionUrl
// and MezonRedirectLayer::$redirectWasPerformed will be set to 'true'
MezonRedirectLayer::redirectTo('./url');
Войти в полноэкранный режим Выход из полноэкранного режима

Инсценировки сессий

Вы также можете подражать методам сеанса:

Conf::setConfigStringValue('session/layer', 'mock');

// method returns 'session-name' if it is used as mock mode
// and return result of session_name() if it is used in real model
MezonSessionLayer::sessionName();

// setting cookie 
MezonSessionLayer::setCookie(
        string $name,
        string $value = "",
        int $expires = 0,
        string $path = "",
        string $domain = "",
        bool $secure = false,
        bool $httponly = false);

// getting session id or setting it
MezonSessionLayer::sessionId(string $id = ''): string;

// saving session data and closing session
MezonSessionLayer::sessionWriteClose();
Войти в полноэкранный режим Выйти из полноэкранного режима

Инсценировки системных методов

Вы также можете высмеивать некоторые вызовы системных методов. Например, die:

Conf::setConfigStringValue('system/layer', 'mock');

// in mock mode field $dieWasCalled will be set to 'true'
// in real mode built-in PHP method 'die' will be called
MezonSystemLayer::die();
Войти в полноэкранный режим Выйти из полноэкранного режима

Что дальше?

Другие статьи можно найти в моем Твиттере

Что такое mezon/infrastructure-layer?

mezon/infrastructure-layer — это:

  • фреймворк для создания легкого насмешливого кода со 100% покрытием кода
  • mezon/infrastructure-layer является частью проекта Mezon
  • репо на github.com: https://github.com/alexdodonov/mezon-infrastructure-layer

Будет здорово, если вы внесете свой вклад в этот проект. Документация, распространение проекта в ваших социальных сетях, исправление ошибок, рефакторинг, или даже отправка проблемы с вопросом или запросом функции. В любом случае спасибо )

Оцените статью
Procodings.ru
Добавить комментарий