Комментарии 10
Отличная статья. Жду полноценную статью от сообщества, как с этим бороться.
Вот несколько моих комментариев, как я работаю с тестами и моментов, которые я пока что не придумал как обойти:
0. По возможности пишем main классы таким образом, чтобы их можно было бы протестировать с помощью unit или @MockitoUnitTest (это те где @InjectMock, я вечно забываю как оно пишется, поэтому даже кастомную аннотацию завел).
1. Если ваш родительский класс с @SpringBootTest делает before и after, в которых полностью очищает таблицы бд, то можно завести наследника, например ComponentTest (как завещал Борисов), который не будет очищать таблицы (т.е. переопределить before и after родителя), но в котором будет полный контекст спринга. И использовать для компонентных тестов. Т.е. для тех тестов, где мокать было бы слишком много, но чистить бд не надо, либо вы сами в конце теста можете почистить только то, что необходимо.
2. @MockBean на все классы, которые ходят по ресту, в родительском классе. Будет удобно мокать результат, контекст спринга закешен.
3. @MockBean на все @Scheduler. Сами же методы шедулеров однострочные, делегируют работу в другой бин, который и тестируем. Контекст спринга закешен. Больше никаких левых select, когда на дебаге пытаешься найти место, откуда вылетает запрос.
4. Фича флаг, через application.property. В тесте рефлекшеном выставляю нужный параметр, в конце теста возвращаю старый. Контекст кешируется. Но такие тесты не переживут рефакторинг. Может есть лучше способ?
Моя боль:
5. @ConditionOnProperty и несколько имплементации бина, подкидываю имплементацию через аннотацию @TestPropertySource над тестом. Контекст не кешируется. Кто как с этим работает?
6. Не придумал пока что, что делать, когда реально нужен @MockBean. Очень жду советов в вашей статье. Пробовал в родительском классе делать @SpyBean, летели исключения, так времени и не было чтобы разобраться до конца. Пока что просто удаляю @MockBean из кода.
@MockBean
на все классы, которые ходят по ресту, в родительском классе.
Я тоже периодически так делаю, но мне постоянно высказывают, что это неправильно и что на самом деле надо мокать сетевые вызовы с помощью Wiremock. А я повторяю, что не вижу ничего страшного в том, чтобы просто замокать сервис. Если сервис неудобно мокать (так бывает, например с фейн клиентами), то сделать под него обёртку и замокать уже её ))
Не придумал пока что, что делать, когда реально нужен
@MockBean
.
Вот я прямо не знаю. Я выношу все @MockBean
в родительский класс (вот как во втором пункте) и как правило мокаю только то, что придётся мокать. То есть то что ходит во внешние сервисы и то, что возвращает настройки. А ситуаций, где нужен полноценный мок для полноценной бизнес-логики... В интеграционных тестах стараюсь избегать. Для этого стараюсь писать юнит тесты (в узком смысле этого выражения) с использованием Мокито
Я тоже периодически так делаю, но мне постоянно высказывают, что это неправильно и что на самом деле надо мокать сетевые вызовы с помощью Wiremock.
Предлагаю компромисс.
Если по ресту ходит готовый клиент -- например, предоставленный сторонним сервисом или feign-клиент, сгенерированный по спеке -- то считаю вполне допустимым его мокать с помощью @MockBean
(один раз в базовом тестовом классе, вестимо, чтобы не плодить контексты).
Если же мы используем что-то низкоуровненное -- всякие restTemplate
, webClient
и прочее, в общем пишем queryParams
и pathVariables
"руками", то лучше Wiremock. Хотя бы из-за того, что "given" будет написано в другом формате и более наглядно. Иначе получается масло масляное -- вызываем restTemplate
с аргументами... и проверяем, что вызываем с правильными аргументами? Нехорошо.
Ещё лучше, конечно, если сторонний эндпоинт выдаст stub-ы в рамках Contract Testing-а (Spring Cloud Contract), но на практике я такого счастья пока не встречал.
Для 3. @MockBean на все @Scheduler.
проще отключить скедулинг в тестах.
может просто не надо spring в тестах?
А как тогда тестировать логику связанную со спрингом? Ну и впринципе как писать интеграционные тесты тогда?
Надо разделять юнит и интеграционные тесты. В юнит-тестах, согласен, спринга в принципе быть не должно (согласно лондонской школе, по крайней мере).
Интеграционных тестов должно быть десятки, но не тысячи на проект.
Вот с БД как? - вот вопрос. Селекты как-то хотелось бы тестировать.
А есть хороший пример таких тестов? Чтобы с тестконтейнерами бд/Кафки, с полной настройкой
воздержусь от слова "хороший", но кейс из этой прекрасной статьи есть в моем примере https://habr.com/ru/articles/824594/. И БД с кафкой тоже
Как сократить время сборки с помощью кеширования контекста от Spring Test