The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:
В то время как фиктивные объекты являются идеальными инструментами для модульного тестирования, использование фиктивных фреймворков может превратить ваши модульные тесты в неподдерживаемый беспорядок. Благодаря им мы часто слышим, что “фиктивы плохи” и “фиктивы злы”.
Корень этой сложности заключается в том, что наши объекты слишком большие. У них много методов, и эти методы возвращают другие объекты, у которых также есть методы. Когда мы передаем фиктивную версию такого объекта в качестве параметра, мы должны убедиться, что все его методы возвращают допустимые объекты.
Это приводит к неизбежной сложности, которая делает модульные тесты практически невозможными поддерживать.
Возьмем интерфейс Region
из jcabi-dynamo в качестве примера (этот отрывок и все остальные в этой статье упрощены для краткости).
Его метод table()
возвращает экземпляр интерфейса Table
, который имеет собственные методы:
Интерфейс Frame
, возвращаемый методом frame()
, также имеет собственные методы. И так далее. Для создания правильно замоканного экземпляра интерфейса Region
обычно требуется создание десятка других мок-объектов. С помощью Mockito это будет выглядеть так:
И все это является всего лишь опорной конструкцией перед фактическим тестированием.
Допустим, вы разрабатываете проект, который использует jcabi-dynamo для управления данными в DynamoDB. Ваш класс может выглядеть примерно так:
Вы можете себе представить, насколько сложно будет провести модульное тестирование этого класса с использованием Mockito, например. Сначала нам нужно смоделировать интерфейс Region
. Затем мы должны имитировать интерфейс Table
и убедиться, что он возвращается методом table()
. Затем нам нужно имитировать интерфейс Frame
и так далее.
Модульный тест будет намного длиннее самого класса. Кроме того, его реальная цель, которая заключается в тестировании получения заработной платы сотрудника, не будет очевидна для читателя.
Более того, когда нам понадобится протестировать аналогичный метод аналогичного класса, нам придется снова начинать моделирование с нуля. Опять же, несколько строк кода, которые будут очень похожи на то, что мы уже написали.
Решение заключается в создании фиктивных классов и их совместной отправке с реальными классами. Именно это делает jcabi-dynamo. Просто посмотрите на его JavaDoc. В нем есть пакет под названием com.jcabi.dynamo.mock
, который содержит только фиктивные классы, подходящие только для модульного тестирования.
Несмотря на то, что их единственная цель - оптимизация модульного тестирования, мы отправляем их вместе с кодом для продакшена, в том же JAR-пакете.
Вот как будет выглядеть тест, когда используется фиктивный класс MkRegion
:
Этот тест кажется очевидным для меня. Сначала мы создаем фиктивный регион DynamoDB, который работает поверх хранилища H2Data
(встроенная база данных H2). Хранилище будет готово для одной таблицы employees
с хэш-ключом name
и одним атрибутом salary
.
Затем мы добавляем запись в таблицу с хэшем Jeff
и зарплатой 50000
.
Наконец, мы создаем экземпляр класса Employee
и проверяем, как он извлекает зарплату из DynamoDB.
В настоящее время я делаю то же самое в почти каждой библиотеке с открытым исходным кодом, с которой работаю. Я создаю коллекцию фиктивных классов, которые упрощают тестирование внутри библиотеки и для ее пользователей.
Кстати, здесь отличная статья на ту же тему: tl;dw: Stop mocking, start testing от Неда Батчелдера.
P.S. Посмотрите также на эту статью по очень похожей теме: Имитация HTTP-сервера в Java.
Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-18 at 05:31