Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/nixel2007/moskito
Библиотека для создания моков и стабов в стиле mockito
https://github.com/nixel2007/moskito
oscript-lib oscript-package
Last synced: about 5 hours ago
JSON representation
Библиотека для создания моков и стабов в стиле mockito
- Host: GitHub
- URL: https://github.com/nixel2007/moskito
- Owner: nixel2007
- License: mit
- Created: 2017-10-13T11:34:50.000Z (about 7 years ago)
- Default Branch: develop
- Last Pushed: 2021-02-19T21:33:34.000Z (over 3 years ago)
- Last Synced: 2023-03-05T22:33:23.096Z (over 1 year ago)
- Topics: oscript-lib, oscript-package
- Language: 1C Enterprise
- Size: 142 KB
- Stars: 5
- Watchers: 5
- Forks: 7
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Moskito - mock this script!
[![CI](https://github.com/nixel2007/moskito/actions/workflows/main.yml/badge.svg)](https://github.com/nixel2007/moskito/actions/workflows/main.yml)
[![Статус порога качества](https://sonar.openbsl.ru/api/project_badges/measure?project=moskito&metric=alert_status)](https://sonar.openbsl.ru/dashboard?id=moskito)
[![Технический долг](https://sonar.openbsl.ru/api/project_badges/measure?project=moskito&metric=sqale_index)](https://sonar.openbsl.ru/dashboard?id=moskito)Библиотека предназначена для создания моков (mock) и стабов (stub) в OneScript. За основу взят фреймворк [mockito](http://site.mockito.org/) для Java.
## Цели создания библиотеки
Периодически в тестировании возникают задачи проверки работы модулей или классов, имеющих внешние зависимости. Этими зависимостями могут быть как безобидные вспомогательные классы (например, библиотеки `cmdline`, `logos`), так и зависимости, требующие определенного "внешнего" состояния. Например, `Файл` или `HTTPСоединение`.
Для возможности эмуляции работы таких классов и была создана эта библиотека.
## Примеры использования
### Эмуляция работы http-соединения
```bsl
HTTPЗапрос = Новый HTTPЗапрос("/ping");
МокСоединение = Мок.Получить(Новый HTTPСоединение("localhost"));
// Вызов метода Получить по умолчанию вернет NULL, без исключений о недоступности сервиса
Результат = МокСоединение.Получить(HTTPЗапрос);
Ожидаем.Что(Результат).Равно(NULL);// Но можно вызвать исключение
МокСоединение.Когда().Получить(HTTPЗапрос).ТогдаВыбрасываетИсключение(Новый ИнформацияОбОшибке("Ресурс недоступен", Новый Структура));
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(HTTPЗапрос);
Ожидаем.Что(МокСоединение).Метод("Получить", МассивПараметров).ВыбрасываетИсключение("Ресурс недоступен");// Начальные свойства мокируемого объекта переносятся в сам мок
Ожидаем.Что(МокСоединение.Сервер).Равно("localhost");// Можно переопределить результат работы метода
МокСоединение.Когда().Получить(HTTPЗапрос).ТогдаВозвращает("Переопределенный ответ");
Результат = МокСоединение.Получить(HTTPЗапрос);
Ожидаем.Что(Результат).Равно("Переопределенный ответ");// Некоторые объекты нельзя создавать через конструктор.
// Для таких объектов можно воспользоваться созданием мока из типа.
Ответ = Мок.Получить(Тип("HTTPОтвет"));
Ответ.КодСостояния = 200;
Ответ.Когда().ПолучитьТелоКакСтроку().ТогдаВозвращает("Переопределенный ответ");// Моки можно вкладывать в моки
МокСоединение.Когда().Получить(HTTPЗапрос).ТогдаВозвращает(Ответ);
Результат = МокСоединение.Получить(HTTPЗапрос);
Ожидаем.Что(Результат.ПолучитьТелоКакСтроку()).Равно("Переопределенный ответ");// При этом вызов метода с другими параметрами продолжит возвращать NULL
Результат = МокСоединение.Получить("/test");
Ожидаем.Что(Результат).Равно(NULL);
```### Использование матчеров
Для переопределения результатов методов не обязательно передавать точные значения параметров. Можно использовать "матчеры". Матчер - это специальная функция, которая проверяет, что параметр удовлетворяет какому-то условию.
```bsl
МокОбъект = Мок.Получить(Тип("Структура"));
// Заставим структуру для проверки всех свойств возвращать "Истина"
МокОбъект.Когда().Свойство(Матчеры.ЛюбаяСтрока()).ТогдаВозвращает(Истина);// Теперь любой вызов метода "Свойства" с переданной строкой будет возвращать "Истина"
Ожидаем.Что(МокОбъект.Свойство("Строка")).Равно(Истина);
Ожидаем.Что(МокОбъект.Свойство("ДругаяСтрока")).Равно(Истина);// Вызов функции, например, с числом, продолжит возвращать NULL
Ожидаем.Что(МокОбъект.Свойство("ДругаяСтрока")).Равно(NULL);```
Матчер - это функция, которая должна вернуть `Истина` или `Ложь`. Вы можете написать матчер любой сложности, используся специальный конструктор.
```bsl
// Функция-матчер принимает минимум один параметр
// Значение - Произвольный - само проверяемое значение
//
// В функции могут содержаться дополнительные параметры. Значения таких параметров должны передаваться
// в виде массива при создании матчера.
//
Функция БольшеТрех(Знач Значение) Экспорт
Возврат Значение > 3;
КонецФункцииМокОбъект = Мок.Получить(Тип("Структура"));
СвойМатчер = Новый Матчер(ЭтотОбъект, "БольшеТрех");
МокОбъект.Когда().Свойство(СвойМатчер).ТогдаВозвращает(Истина);Ожидаем.Что(МокОбъект.Свойство(0)).Равно(NULL);
Ожидаем.Что(МокОбъект.Свойство(3)).Равно(NULL);
Ожидаем.Что(МокОбъект.Свойство(4)).Равно(Истина);```
### Переопределение с использованием Ответов
В сложных тестовых случаях методов `ТогдаВозвращает` и `ТогдаВыбрасываетИсключение` может не хватать. Вы можете реализовать более сложную логику ответа с использованием метода `ТогдаОтвечает`
```bsl
// Допустим у нас есть функция, которая просто возвращает строковую информацию
// о вызванном методе.
Функция ВернутьИнформациюОВызове(Знач ИнформацияОВызове) Экспорт// Параметр ИнформацияОВызове хранит данные о самом моке, вызываемом методе,
// и массиве параметров, с которым вызвали этот метод.
МокОбъект = ИнформацияОВызове.Мок();
ИмяМетода = ИнформацияОВызове.ИмяМетода();
Параметры = ИнформацияОВызове.Параметры();// Преобразование массива в строку.
Параметры = ПроцессорыКоллекций.ИзКоллекции(Параметры).ВСтроку(", ");// Произовльное возвращаемое значение
Возврат СтрШаблон("Вызван метод <%1> с параметрами <%2>", ИмяМетода, Параметры);
КонецФункции// Создадим указатель на функцию, которая должна вызываться при "ответе"
Ответ = Новый Ответ(ЭтотОбъект, "ВернутьИнформациюОВызове");МокОбъект = Мок.Получить(Тип("Структура"));
// Когда у мока вызывается метод Свойство(), срабатывает вызов функции, заложенной в "Ответе"
МокОбъект.Когда().Свойство(Матчеры.ЛюбаяСтрока(), Матчеры.ЛюбоеЗначение()).ТогдаОтвечает(Ответ);// Вызовем функцию
Результат = МокОбъект.Свойство("Поле");// В "Результате" получим строку, возвращенную функцией ВернутьИнформациюОВызове
Ожидаем.Что(Результат).Равно("Вызван метод <Свойство> с параметрами <Поле, >");```
### Проверка вызова методов
```bsl
// Допустим у нас есть класс, принимающий в себя HTTPСоединение, и вызывающий у него метод Получить()
// Проверим, что метод Получить() действительно вызывалсяМойКласс = Новый МойКласс();
МокСоединение = Мок.Получить(Новый HTTPСоединение("localhost"));МойКласс.УстановитьКонтекст(МокСоединение);
МойКласс.ВызватьМетодКоторыйДолженДернутьПолучить("/ping");// Если метод Получить не вызывался, будет выдано исключение
МокСоединение.ПроверитьЧтоВызывалсяМетод().Получить("/ping");```
### Режим "шпиона" (spy)
```bsl
// Создаем нового шпиона над Структурой
МокСтруктура = Мок.Следить(Новый Структура);// Шпион вызывает реальные методы объекта
МокСтруктура.Вставить("Ключ1", 1);// Методы "внутреннего" объекта работают как обычно
Ожидаем.Что(МокСтруктура.Количество()).Равно(1);МокСтруктура.Вставить("Ключ2", 2);
// Однако, мы можем все еще можем переопределить (stub) результат работы любого метода
МокСтруктура.Когда().Количество().ТогдаВозвращает(999);// В этом случае будет возвращаться наше значение.
Ожидаем.Что(МокСтруктура.Количество()).Равно(999);```
## Имеющиеся ограничения
* В силу ограничений движка на создание методов с именами, совпадающими с именами глобальных методов, не от всех объектов можно создать идентичный мок. Например, если создать мок от `Массив`, то метод `Найти()`, совпадающий по имени с глобальным методом, будет переименован в метод `_Найти()`. `Структура` же замокается без проблем.