21 KiB
Мокито
Мокито - модуль созданный по образу популярного java-фреймворка для тестирования Mockito. Расширяет возможности тестирования, позволяет легко менять логику работы системы подменяя результаты работы методов, отключая какие-либо алгоритмы и проверки.
Юнит-тесты, это тесты конкретных методов в отрыве от системы - контролировать данные используемые методом, изменение логики и ошибки других объектов не должны аффектить на тест. В реальных конфигурациях объекты тесно связаны друг с другом, поэтому добиться контроля влияющих данных очень сложно. Обычно приходится создавать большой объем тестовых данных. А добиться изоляции от изменения логики других объектов почти невозможно. Мокирование же позволяет изменить логику работы системы таким образом, чтобы тестируемый метод не вызывал другие методы и использовал уже подготовленные данные. Например, для тестирования проведения реализации товаров мы можем подменить результат функции формирующей таблицу проводок и избежать сложной подготовки данных.
С помощью Мокито разработчик указывает, что делать при вызове определенных методов - вернуть нужный результат, вызвать исключение или просто не трогать ненужные методы. После тестирования разработчик может запросить и проверить статистику о вызовах, как и какие методы были вызваны.
Пример:
ОтветСерверы = ОтветУспешногоЗапроса("Серверы");
ОтветДиски = ОтветУспешногоЗапроса("Диски");
Мокито.Обучение(РаботаСHTTP)
.Когда(РаботаСHTTP.ВыполнитьЗапрос(ПараметрыПодключения, "/hosts", "GET"))
.Вернуть(ОтветСерверы)
.Когда(РаботаСHTTP.ВыполнитьЗапрос(ПараметрыПодключения, "/disks", "GET"))
.Вернуть(ОтветДиски)
.Прогон();
Результат = БиллингДрайверГипервизорNutanix.Серверы(ПараметрыПодключения);
В этом примере изменяется работа модуля РаботаСHTTP
, для функции ВыполнитьЗапрос
, вызванной с нужными параметрами будет возвращено подготовленное значение, а сам метод не будет вызван.
Мы получим ожидаемые ответы на запросы к сторонней системе и уйдет от проблем связанных с ней - недоступность, изменение контрактов и т.д.
Работа с Мокито делится на 3 стадии:
- Обучение - настраиваем поведение методов системы
- Прогон - выполнение теста целевого метода
- Проверка - анализ вызовов
Использование
Настройка мокируемых методов
Для работы Мокито вам необходимо добавить интересующие методы в тестовое расширение.
Эта позволит управлять поведением метода:
- подменять результат во время выполнения теста
- использовать явный вызов метода с параметрами на стадии обучения, например
Мокито.Обучение(Справочники.ИсточникиДанных).Когда(Справочники.ИсточникиДанных.СохраненныеБезопасныеДанные(Справочник)).Вернуть(Результат)
- использовать явный вызов метода с параметрами на стадии проверки, например
Мокито.Проверить(Справочники.ИсточникиДанных).КоличествоВызовов(Справочники.ИсточникиДанных.СохраненныеБезопасныеДанные(Справочник)).Больше(1)
Примеры добавления методов в расширение:
Метод общего модуля
Добавляем обработку метода ИнициализироватьВнешнююКомпоненту
общего модуля ОбщегоНазначенияКлиентСервер
&Вместо("ИнициализироватьВнешнююКомпоненту")
Функция ЮТИнициализироватьВнешнююКомпоненту(ИмяМакета, ИмяКомпоненты, ВызыватьИсключение, ПаузаЧерезКомпоненту) Экспорт
// Собираем параметры в массив
ПараметрыМетода = Мокито.МассивПараметров(ИмяМакета, ИмяКомпоненты, ВызыватьИсключение, ПаузаЧерезКомпоненту);
// Отправляем данные на анализ
ПрерватьВыполнение = Ложь;
Результат = Мокито.АнализВызова(ОбщегоНазначенияКлиентСервер, "ИнициализироватьВнешнююКомпоненту", ПараметрыМетода, ПрерватьВыполнение);
// Обрабатываем результат анализа
Если НЕ ПрерватьВыполнение Тогда
Возврат ПродолжитьВызов(ИмяМакета, ИмяКомпоненты, ВызыватьИсключение, ПаузаЧерезКомпоненту);
Иначе
Возврат Результат;
КонецЕсли;
КонецФункции
Метод модуля менеджера
Добавляем обработку метода СохраненныеБезопасныеДанные
модуля менеджера справочника Справочники.ИсточникиДанных
&Вместо("СохраненныеБезопасныеДанные")
Функция ЮТСохраненныеБезопасныеДанные(Владелец, Знач Ключи) Экспорт
// Собираем параметры в массив
ПараметрыМетода = Мокито.МассивПараметров(Владелец, Ключи);
// Отправляем данные на анализ
ПрерватьВыполнение = Ложь;
Результат = Мокито.АнализВызова(Справочники.ИсточникиДанных, "СохраненныеБезопасныеДанные", ПараметрыМетода, ПрерватьВыполнение);
// Обрабатываем результат анализа
Если НЕ ПрерватьВыполнение Тогда
Возврат ПродолжитьВызов(Владелец, Ключи);
Иначе
Возврат Результат;
КонецЕсли;
КонецФункции
Метод модуля объекта
Добавляем обработку приватного метода ПеренестиДанныеВБезопасноеХранилище
модуля объекта справочника Справочники.ИсточникиДанных
&Вместо("ПеренестиДанныеВБезопасноеХранилище")
Функция ЮТПеренестиДанныеВБезопасноеХранилище(Ключи)
// Собираем параметры в массив
ПараметрыМетода = Мокито.МассивПараметров(Ключи);
// Отправляем данные на анализ
ПрерватьВыполнение = Ложь;
Результат = Мокито.АнализВызова(ЭтотОбъект, "ПеренестиДанныеВБезопасноеХранилище", ПараметрыМетода, ПрерватьВыполнение);
// Обрабатываем результат анализа
Если НЕ ПрерватьВыполнение Тогда
Возврат ПродолжитьВызов(Ключи);
Иначе
Возврат Результат;
КонецЕсли;
КонецФункции
Обучение
Самая первая стадия при написании тестов использующих моки - обучение. Мы создаем правила как будет вести себя метод при различных вариантах вызова. Правило состоит из условий проверки параметров и действия выполняемого при соблюдении условий.
Условия можно задать на равенство определенному значению, на проверку типа переданного значения или же безусловно принимать любый параметры
Существует 2 основных подхода к формированию условий вызова:
- Явный вызов метода с параметрами:
Обучение(РаботаСHTTP).Когда(РаботаСHTTP.ОтправитьОбъектНаСервер(ИсточникДанных, Данные)).Вернуть(2)
- Указание имени метода и набора параметров:
Обучение(РаботаСHTTP).Когда("ОтправитьОбъектНаСервер", Мокито.МассивПараметров(ИсточникДанных, Данные)).Вернуть(2)
Первый вариант имеет ряд недостатков:
-
Работает только для экспортных методов
-
Необходимо передавать все обязательные параметры или использовать для них маску
Мокито.ЛюбойПараметр()
-
Если не указывать необязательные параметры, то их значения по умолчанию попадут в настройку. Покажу на примере. Имеется метод
Функция Метод(Параметр1, Параметр2, Параметр3 = 3)
Настройка
Когда(Метод(1, 2)).Вернуть(0)
, в результате ноль мы получим для вызововМетод(1, 2)
Метод(1, 2, 3)
Для вызова
Метод(1, 2, 4)
будет выполнен основной алгоритм метода.А для настройки
Когда("Метод", Мокито.МассивПараметров(1, 2)).Вернуть(0)
все три варианта вызова вернут ноль.
После того как определились с условием вызова указанным в методе Когда
нужно указать реакцию. Возможные реакции:
Вернуть
- вернуть указанное значениеВыброситьИсключение
- вызвать исключение с переданным текстомПропустить
- пропустить выполнение метод (актуально для процедур)
Примеры формирования различных вариантов условий
Имеется метод:
Функция ОтправитьОбъектНаСервер(ИсточникДанных, Объект, HTTPМетод = "POST",
ТипКонтента = "json", Преобразование = Неопределено,
ДопНастройки = Неопределено, Ответ = Неопределено, ОтветВСтруктуру = Ложь,
ТелоОтветаВХранилище = Ложь) Экспорт
- Переопределить все вызовы метода - указываем имя метода без указания параметров
Мокито.Обучение(РаботаСHTTP).Когда("ОтправитьОбъектНаСервер").Вернуть(1)
- Переопределить вызов, когда первый параметр имеет определенное значение
Мокито.Обучение(РаботаСHTTP).Когда("ОтправитьОбъектНаСервер", Мокито.МассивПараметров(ИсточникДанных)).Вернуть(2)
Мокито.Обучение(РаботаСHTTP).Когда(РаботаСHTTP.ОтправитьОбъектНаСервер(ИсточникДанных, Мокито.ЛюбойПараметр()).Вернуть(2)
. Тут используется маскаМокито.ЛюбойПараметр()
, тк второй параметр является обязательным
- Переопределить вызов, когда второй параметр имеет определенное значение
Мокито.Обучение(РаботаСHTTP).Когда("ОтправитьОбъектНаСервер", Мокито.МассивПараметров(Мокито.ЛюбойПараметр(), Объект)).Вернуть(2)
Мокито.Обучение(РаботаСHTTP).Когда(РаботаСHTTP.ОтправитьОбъектНаСервер(Мокито.ЛюбойПараметр(), Объект).Вернуть(2)
.
- Условие на тип параметра
Мокито.Обучение(РаботаСHTTP).Когда("ОтправитьОбъектНаСервер", Мокито.МассивПараметров(Мокито.ТипизированныйПараметр(ТипИсточникДанных), Мокито.ЧисловойПараметр())).Вернуть(3)
Мокито.Обучение(РаботаСHTTP).Когда(РаботаСHTTP.ОтправитьОбъектНаСервер(Мокито.ТипизированныйПараметр(ТипИсточникДанных), Мокито.ЧисловойПараметр()).Вернуть(3)
Прогон
После обучения, настройки реакций на вызовы методов, можно запускать тест нужного метода. Для перехода к этому режиму работы Мокито используется метод Прогон
.
Все вызовы к настроенным методам (добавленным в расширение) будут перехватываться и анализироваться на совпадение условий вызова. Для вызовов, у которых есть подходящая "реакция" будет переопределено выполнение и запустится соответствующая реакция (вернуть значение, вызвать исключение и тд), для прочих - выполнение продолжится.
// Настройка
Мокито.Обучение(РаботаСHTTP)
.Когда("ОтправитьОбъектНаСервер", Мокито.МассивПараметров(Мокито.ЛюбойПараметр(), Мокито.ЛюбойПараметр()))
.Вернуть(РезультатПоУмолчанию)
.Когда("ОтправитьОбъектНаСервер", Мокито.МассивПараметров(Справочники.ИсточникиДанных.FTP, 2))
.Вернуть(2)
.Прогон(); // Перевод в режим прогона теста
Результат = РаботаСHTTP.ОтправитьОбъектНаСервер(ИсточникДанных, Данные); // Результат будет равен переменной РезультатПоУмолчанию
Результат = РаботаСHTTP.ОтправитьОбъектНаСервер(Справочники.ИсточникиДанных.FTP, 2); // Результат будет равен 2
Проверка
После прогона теста можно проверить какие методы, с какими параметрами вызывались. Для этих целей необходимо воспользоваться методом Проверить
Мокито.Проверить(РаботаСHTTP) // Устанавливаем проверяемый объект
.КоличествоВызовов(РаботаСHTTP.ОтправитьОбъектНаСервер(ЛюбойПараметр, Мокито.ЧисловойПараметр())) // Условия поиска вызовов
.Больше(1) // Проверки
.Равно(2)
.КоличествоВызовов("ОтправитьОбъектНаСервер").Заполнено().Равно(3).Меньше(6)
.КоличествоВызовов("ОтправитьЗапросHTTP").Пусто().Меньше(1)
.КоличествоВызовов(РаботаСHTTP.ОтправитьОбъектНаСервер(1, 2)).Равно(1)
.КоличествоВызовов(РаботаСHTTP.ОтправитьОбъектНаСервер(ЛюбойПараметр, ЛюбойПараметр)).Равно(3)
.КоличествоВызовов(РаботаСHTTP.ОтправитьОбъектНаСервер(Мокито.ТипизированныйПараметр(ТипИсточникДанных), ЛюбойПараметр)).Равно(1)
Принцип формирования проверки:
- Указываем проверяемый объект
Проверить(РаботаСHTTP)
. - Указываем условия поиска вызовов метода. Логика формирования условия такая же как при обучении.
Например,
КоличествоВызовов(РаботаСHTTP.ОтправитьОбъектНаСервер(ЛюбойПараметр, Мокито.ЧисловойПараметр()))
Соберет все вызовы методаРаботаСHTTP.ОтправитьОбъектНаСервер
, к которых вторым параметром идет число, а 3й и последующий параметры имеют значения по умолчанию. - Проверяем собранные вызовы:
Заполнено
- есть вызовы метода по указанным условиямПусто
- нет вызовов метода по указанным условиямРавно
- количество вызовов попавших под условия равно указанному значениюБольше
- количество вызовов попавших под условия больше указанного значенияМеньше
- количество вызовов попавших под условия меньше указанного значения
Кейсы использования*
* В примерах опускается часть добавления метода в расширение
-
Подмена результат функции для любого вызова
Мокито.Обучение(РаботаСHTTP) .Когда("ОтправитьОбъектНаСервер") .Вернуть(1)
-
Выключение алгоритма проведения документа
Мокито.Обучение(СсылкаИлиОбъектДокумент) .Когда("ОбработкаПроведения") .Пропустить()
-
Выбросить исключение, если в метод передан некорректный набор параметров
Мокито.Обучение(РаботаСHTTP) .Когда("ОтправитьОбъектНаСервер") .ВыброситьИсключение("Не верные параметры вызова") .Когда(РаботаСHTTP.ОтправитьОбъектНаСервер(Справочники.ИсточникиДанных.FTP, Мокито.ЛюбойПараметр())) .ВыполнитьМетод();