Как стать автором
Обновить
6
0

Пользователь

Отправить сообщение

Логично, что-то не подумал, спасибо, попробую.

При использовании SpringBootTest кешируется спринг контекст. Если сделать класс родитель тестов, прописать в нем эту аннотацию и все end to end тесты наследовать от родителя, то контекст будет построен один раз на все тесты. Но есть нюансы, легко сломать, была статья на этой неделе на Хабре.

https://habr.com/ru/companies/spring_aio/articles/905586/

Mockito unit test - это прекрасно, но если заинжектить что-то - пройдись по двадцати тестам, допиши что вернет мок, это бесит. Обычно переписываю mockito unit test на component test, если инжектов больше чем 3. Component test это имплементация родительского теста, с контекстом спринга, но без очистки бд.

Mockmvc и mockjpa ни разу не видел на живом проекте. Один раз попробовал, не удобно, component test наше всё.

Отличная статья. Жду полноценную статью от сообщества, как с этим бороться.

Вот несколько моих комментариев, как я работаю с тестами и моментов, которые я пока что не придумал как обойти:

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 из кода.

Интересно, спасибо за статью.

  1. Добавь, пожалуйста, сравнение по памяти.

  2. Всё-таки самое частое использование List - добавление в конец с последующей итерацией. И в таком кейсе использования ваша структура и LinkedList делают доп нагрузку на хип. К тому же ArrayList можно сразу задать нужного размера.

p.s. а ещё есть стримы)

На 20 метровую комнату - два ультразвуковых, с выхлопом 300 в час, с шумом около 30 дБ, без подсветки, с доливом воды сверху.

Практика. Оптимизировал тесты на одном из проектов.

Использование аннотации @MockBean в тестах, которые будут extends ваш родительский тест с @SpringBootTest, приводит к созданию нового спринг контекста. @SpyBean над бином в родительском тесте и Mockito.when() в дочернем - спринг контекст возьмётся из кеша. Если вы не хотите, чтобы тесты вашего проекта проходили час - надо постараться не плодить контексты спринга.

Спасибо за вопрос.


Я не пробовал, но судя по документации, для "входов" в приложение через @RestController - @RequestScope может прокатить.


Я использовал @RestController в статье для примера визуализации workflow.
На практике могут быть и другие "входы" в приложение, например @Scheduler или брокер сообщений, которые не проходят через сервлет, и соответственно @RequestScope не будет работать.

Спасибо, что делишься знаниями.

А если бы два метода, помеченные @Scheduled находились бы в разных классах, была бы проблема, что вторая джоба не стартует пока не выполнится первая? Обработчик шедулеров один на приложение или один на класс?

И ещё, если микросервисы + шедлок, то видимо проблема не так актуальна, поток из другой поды сервиса отработает.

Крутяк, спасибо. Единственное, что я бы добавил, по поводу тредлокала. Не забывайте его очищать, или инициализировать каждый раз. Дело в том, что поток может выполнить работу, леч в пул потоков, и пойти делать ту же самую работу, но для других данных, а в тредлокале старые данные. Чуть позже я напишу мини статью об этом, и предложу свои варианты.

Существует 2 очень похожих паттерна, которые в клиентском коде выглядят как вертикальная запись через точку: builder, fluent interface.

С практической точки зрения я бы классифицировал их следующим образом:

  1. Ленивость - действие выполняется в момент вызова промежуточного метода, или действие выполняется только в момент вызова терминальной операции.

  2. По типу возвращаемого значения. Возвращается тот же самый тип, или другой.

Представленный пример можно назвать ленивым спринговым билдером.

Вы на какой версии hibernate FetchMode.SUBSELECT используете? Полагаю что 6.3, который идёт в spring boot 3.

Я пробовал в 5.6.4 - у меня не работало, в итоге написал динамический энтити граф, тяну им.

Поясню.

Не хватает красивого примера прикладного, боевого, ентерпрайз-продакшн кода, где бы демонстрировалось преимущество использования данной библиотеки. Демонстрировалось бы как легко она помогает решить какую-то проблему при написании кода.

Потому что с моей колокольни, прикладного, боевого, ентерпрайз-продакшн разработчика, когда spring boot и mapstruct "стандарт" в отрасли - не видно кейсов применения данной библиотеки. Поэтому удивлённо спрашиваю, у вас в ваших проектах, голая java?

  1. Не хватает красивого примера боевого кода.

  2. Смотрю я на functional N и думаю, у вас голая java в проекте? Spring и mupstruct не используете? В дефолтный .map() стрима или опшионала передаешь бин с понятным методом мапинга...

Информация

В рейтинге
5 332-й
Зарегистрирован
Активность

Специализация

Бэкенд разработчик
Ведущий
Java