No video

Правила хорошего UNIT-теста на примере java и spring boot

  Рет қаралды 16,352

Kirill Grishchuk - Software Engineer

Kirill Grishchuk - Software Engineer

Күн бұрын

Всем привет, в этом видео покажу как делать unit тестирование типичного spring-boot приложения.
Проект на github:
github.com/Kirya522/medium-po...
Telegram канал для обратной связи:
t.me/kirya522
Лайв канал
/ @kirya522-live
Поддержать канал
pay.cloudtips.ru/p/f4934136
www.donationalerts.com/r/kiry...
Содержание:
0:00 - Введение
0:21 - Готовый пример
0:35 - Типичное SpringBoot приложение
1:10 - Как начинается unit тестирование
1:30 - Тестирование Repository
1:55 - Сколько методов столько и тестов
2:03 - Тесты не должны зависеть друг от друга
2:20 - Не инициализировать лишние зависимости
2:50 - Как назвать тест
3:10 - Содержание теста, модель AAA
3:40 - Когда использовать моки
4:20 - Самые типичные Unit тесты
5:12 - Тестирование Service
5:50 - Тестирование с моками зависимостей
6:15 - Полезные аннотации Mockito
7:05 - Настройка моков зависимостей
7:50 - Проверка вызовов через verify
8:30 - Как проверять void метод
9:03 - Тестирование Controller
9:13 - Тест с большим количеством моков
10:25 - Разница Unit и Integration тестов
11:00 - Кратко о SpringBootTest
11:40 - Зона ответственности Unit тестов
11:55 - Покрытие кода тестами
12:30 - Как читать отчет о покрытии
13:00 - Как происходит ревью тестов
13:40 - Возможная бессмысленность тестов
14:40 - Планы про нагрузочное тестирование

Пікірлер: 63
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Telegram канал с анонсами, обсуждениями, вопросами по видео. t.me/kirya522
@alexsecret3496
@alexsecret3496 25 күн бұрын
респект за показ-рассказ) ощущение что я писал тесты всю жизнь!) ну а теперь приступим...
@faniskhalikov9736
@faniskhalikov9736 Жыл бұрын
Спасибо! Концентрация полезности зашкаливает )) Как раз то, что мне нужно для пэт-проекта!
@user-uw7zl3gm5r
@user-uw7zl3gm5r Жыл бұрын
спасибо большое за видео,приятно смотреть и слушать😃
@crew534
@crew534 Жыл бұрын
Прекрасное видео, очень хорошая подача, благодарю за помощь
@user-de4oq1uu9h
@user-de4oq1uu9h 9 ай бұрын
Спасибо большое, очень много интересного узнал! Круто!!
@DanChofire
@DanChofire 7 ай бұрын
Спасибо лектору, очень крутая подача и материал.
@raccoon8230
@raccoon8230 Жыл бұрын
Спасибо! Подача - 🔥
@DuncanBatat
@DuncanBatat Жыл бұрын
Спасибо за видео! Очень помогло осознать цели юнит-тестов и начать разбираться с Moсkito.
@kirya522-dev
@kirya522-dev Жыл бұрын
Рад был помочь
@alexidrlen1538
@alexidrlen1538 Жыл бұрын
Очень круто объясняете, спасибо большое!!!
@kirya522-dev
@kirya522-dev Жыл бұрын
Скоро сделаю по интеграционным тестам
@mustFLEXboi
@mustFLEXboi 9 ай бұрын
Спасибо. Очень полезно
@user-iu6yz6ck6h
@user-iu6yz6ck6h 2 жыл бұрын
Подписался на канал. Спасибо за видео )
@lexxx1994
@lexxx1994 2 жыл бұрын
годно 👏
@kifacapybara7309
@kifacapybara7309 7 ай бұрын
спасибо, очень полезно! ненавижу тестирование)
@alexeikopendakov3348
@alexeikopendakov3348 6 ай бұрын
Казалось бы банальщина, но очень нужная! Спасибо!
@alexanderkadatskiy7986
@alexanderkadatskiy7986 2 жыл бұрын
Привет! Отличное видео! А примера с интеграционными тестами с использованием спрингового контекста не планируется?
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Хотел сделать, но там гораздо больше надо рассказать. - mockmvc - конфиги - test containers
@alexanderkadatskiy7986
@alexanderkadatskiy7986 2 жыл бұрын
@@kirya522-dev Больше - не меньше) Можно на несколько видосов разбить
@TheLordGamesTv
@TheLordGamesTv 2 жыл бұрын
@@kirya522-dev + про интеграционные хотелось бы видео, ждем
@stepan-klyukin
@stepan-klyukin 3 ай бұрын
А что делать если в результате работы метода у обьекта должно измениться одно поле? Мокать все поля кроме этого поля и делать бва таких обьекта но разным значением этого поля?
@kirya522-dev
@kirya522-dev 3 ай бұрын
Сделать свойство и доступ через геттер и его мокнуть
@SplashDmg2011
@SplashDmg2011 Жыл бұрын
Имена тестов типа "saveSmth_shouldDoSmth_whenSmth" и т.д. уже не стоит выдумывать, т.к. это трудно читается и вообще имя метода не для этого предназначено) в jUnit есть аннотация @DisplayName, которая позволяет человеческим языком (обычным текстом) написать, что именно проверяет тест
@kirya522-dev
@kirya522-dev Жыл бұрын
Да, но тогда и аннотацию и имя надо поддерживать, а так называешь тесты в таком стиле и не заморачиваешься
@SplashDmg2011
@SplashDmg2011 Жыл бұрын
@@kirya522-devимя поддерживать не надо, оно ни на что не влияет) можно хоть test1, test2 и т.д. называть. А вот читать строку "On save service should call repository.save()" гораздо приятней, чем ту конструкцию без пробелов и с подчеркиваниями) Мне кажется у тебя просто привычка уже выработалась просто. Вот у меня опыта поменьше, я почти сразу стал пользоваться @DisplayName, т.к. она уже появилась, когда я начал работать, и поэтому мне сразу этот метод кажется гораздо более удобным)) И это еще самый простой пример сценария я привел. А если тест проверяют какую-то сложную бизнес-логику, которую двумя словами не описать? Тогда придется городить название метода длиной в экран и читать его будет суперсложно. А в аннотации можно то же самое написать с пробелами и понятным языком) Но есть нюанс: аннотация появилась в JUnit5, и на легаси-проектах с JUnit4 использовать ее не получится)
@Das.Kleine.Krokodil
@Das.Kleine.Krokodil Жыл бұрын
Нужно ли как то тестировать репозиторий если в нем нет кода? по типу такого: @Repository public interface EmployeeRepository extends JpaRepository { }
@kirya522-dev
@kirya522-dev Жыл бұрын
фреймворки тестировать неблагородное дело
@SplashDmg2011
@SplashDmg2011 Жыл бұрын
Я бы сказал немного иначе: тестированием фреймворков должны заниматься создатели этих фреймворков, нам повторно это делать не нужно)
@mr.whitesnow
@mr.whitesnow 6 ай бұрын
создавать тестовые данные в тесте - плохая практика, на мой взгляд например, у Вас тест проверяющий поиск по репе, в котором сначала Вы пишете в репу, а потом делаете по этим данным поиск а что если запись в репу не случилась, то упадет тест, который тестит поиск и в отчете будет видно что сломался поиск по репе, что не соответствует действительности и может быть принято неверное решение, например, о готовности релиза на мой взгляд, правильный подход - это когда тестовые данные уже готовы до начала выполнения теста, т.е. если мы тестируем поиск данных, то данные для этого поиска уже должны быть там
@kirya522-dev
@kirya522-dev 6 ай бұрын
Есть соглашение, что должно быть ровно наоборот. Тест создаёт данные и их же ищет, теперь вопрос почему. Потому что логика создания и наполнения данных тоже изменяется, программное управление созданием упрощает поддержку. А когда все данные есть и полное совпадение, это acceptance тестирование, самая дорогая часть пирамиды тестирования и самая не гибкая, нужна скорее в полноценных сценариях пользователя, а не в узких кусочках
@mr.whitesnow
@mr.whitesnow 6 ай бұрын
согласен, что не удобно управлять тестовыми данными но в вашем случает тест проверяет не только то, что должен и может упасть раньше сути тесткейса в итоге менеджер смотрит результат с системе отчетности и возможно принимает неверное решение я эт не придумал, это из реальной жизни пример 😊
@The_Vict0r
@The_Vict0r 2 жыл бұрын
Полезное видео, спасибо! А может EventBuilder лучше поместить на уровень сервисов? Это ведь уже работа с сущностями, а "контроллер должен быть тупым" :)
@kirya522-dev
@kirya522-dev 2 жыл бұрын
А тут получается разделение ответственности, что есть core сервисы которые работают с сущностями, а контроллер отвечает именно за их представление, но на практике чаще это выражается ещё в один сервис который называется Api и в нем логика и маппинг
@The_Vict0r
@The_Vict0r 2 жыл бұрын
@@kirya522-dev Ага. И этот Api находится в слое сервисов - я правильно понимаю?
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Предлагаю перейти от слоев к мавен модулям, чтобы было понятнее. Есть соответственно модули: - сервисов - Api И логика маппинга находится в модуле Api на слое сервисов, надеюсь не слишком запутал
@The_Vict0r
@The_Vict0r 2 жыл бұрын
@@kirya522-dev Ну, я попробую понять )
@wildjoe6259
@wildjoe6259 2 жыл бұрын
Привет! Спасибо за видео! Такой вопрос, а mockMvc тесты не юзаете? типо mockMvc.perform(get("/api/some-url")) .andDo(print()) .andExpect(status().isOk()) .andExpect(content().json(obj.writeValueAsString(somePayload))); И к какому типу тестов нужно их отностить? (явно не юнит, но и не интеграционные, так как ответы от внешних систем мокируются)
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Привет, для mockmvc надо спринговый контекст, и идея там проверять взаимодействие как раз 2+ классов, как например сериализатор, десериализатор из json и ваша логика. Поэтому я отношу к интеграционным
@SplashDmg2011
@SplashDmg2011 Жыл бұрын
Немного придерусь к вопросу: "тесты в проде" вообще не юзают, они прогоняются перед сборкой, а затем "вырезаются" из продового билда, они там уже не нужны)
@nickivanov7903
@nickivanov7903 2 жыл бұрын
контроллер можно было тестить через web mvc test
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Да, но так получится уже интеграционный тест с контекстом🙂
@georgepro8481
@georgepro8481 2 жыл бұрын
Привет! Для 8й джавы сработает так же?
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Да, вроде бы все что рассказал работает на 8
@69ultrapotato
@69ultrapotato Жыл бұрын
Юнит тесты спринг-бинов очень хрупки. Поменял тип/удалил одно поле в дто/сущности - 50 тестов сломалось. Добавил в сервис еще один бин. Он не замокан в 50 тестах - они сломались. И так до бесконечности. Юнитами например кастомные валидаторы отлично покрываются. К тому же куча всего юнитами просто не покрывается, потому что логика она в аннотациях, а не только в коде. Поэтому пишу интеграционные разного масштаба, а юниты только в крайнем случае, когда логика в одном методе сервиса очень заковыристая, и мокать надо не безумно много(но это обычно признак, что нужно выделить еще один сервис).
@kirya522-dev
@kirya522-dev Жыл бұрын
Есть аннотации для тестов по типу @mock и в итоге тесты расширяются без особых проблем
@kirya522-dev
@kirya522-dev Жыл бұрын
А тест на аннотацию и валидаторы можно написать один раз и их везде использовать
@Das.Kleine.Krokodil
@Das.Kleine.Krokodil Жыл бұрын
А нормально так контроллер тестировать, явно вызывая его методы? На проде так делаете, нет проблем? А то все материалы на которые натыкаюсь, используют @WebMvcTest и MockMvc Например как поступаете с BindingResult?
@kirya522-dev
@kirya522-dev Жыл бұрын
Можно отдельно протестировать фреймворк если надо интеграционным тестом, сериализацию проверить, аутентификацию авторизацию, сделать один такой тест или парочку если различные механизмы есть. А в контроллерах больше не это делать, так тесты гораздо быстрее работают, если механизм сломается, сломаются тесты которые за него отвечают, но везде одинаковые подходы надо использовать. Что тоже звучит правильно Когда 40000+ тестов на контроллеры, поднятие контекста для запроса, сериализация и тд могут занимать 3/4 времени выполнения.
@kirya522-dev
@kirya522-dev Жыл бұрын
Это все применимо для простых сценариев, если необходимо что-то сложное, например интеграцию проверить или весь flow, то надо писать интеграционный тест
@kirya522-dev
@kirya522-dev Жыл бұрын
И дополнительно ролик только по unit тестам 😀
@Das.Kleine.Krokodil
@Das.Kleine.Krokodil Жыл бұрын
@@kirya522-dev спасибо
@alexricher2554
@alexricher2554 2 жыл бұрын
У тебя очень хорошо получается объяснять! Было бы круто, если бы ты сделал видео на тему: как запустить простейшее spring boot приложение с БД. А то уже пару дней маюсь, никак не получается: бд создаётся, а таблица нет. Мб скрипт надо какой закинуть, чтобы он при запуске контейнера создавал таблицу? Не знаешь, как это вообще делается?
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Вообще несколько есть способов, самый простой liquibase
@zhennik263
@zhennik263 2 жыл бұрын
Ну самый простой вариант это заставить hibernate создавать таблицы. А нормальный вариант это да, liqibase
@alexricher2554
@alexricher2554 2 жыл бұрын
@@kirya522-dev эх, как давно это было. Уже работаю на позиции Джуна)
@alejandrospencio5524
@alejandrospencio5524 2 жыл бұрын
а приватные методы вы проверяете ?
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Приватные методы тестировать не надо, тестируется поведение публичных интерфейсов, приватные должны быть использованы в них и будут покрыты автоматически
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Но иногда есть плохой код, который неудобно рефакторить, то private метод становится package-private с аннотацией @VisibleForTesting и тестируется отдельно
@alejandrospencio5524
@alejandrospencio5524 2 жыл бұрын
@@kirya522-dev спасибо, не знал )
@user-gv3zn1us6s
@user-gv3zn1us6s 11 ай бұрын
Зачем людям видеть лицо лектора? Это отвлекает от кода. Непонятное самолюбование
@kirya522-dev
@kirya522-dev 11 ай бұрын
Кому-то наоборот важно видеть, под всех не подстроюсь
@user-gw6df6ns7e
@user-gw6df6ns7e 9 ай бұрын
Он художник, он так видит. Кто то любит, чтобы ролик не был обезличен. Кто то наоборот.
Spring Boot. JUnit 5. Пишем первый юнит-тест
20:30
Survive 100 Days In Nuclear Bunker, Win $500,000
32:21
MrBeast
Рет қаралды 143 МЛН
Comfortable 🤣 #comedy #funny
00:34
Micky Makeover
Рет қаралды 15 МЛН
Inside Out 2: Who is the strongest? Joy vs Envy vs Anger #shorts #animation
00:22
Best Toilet Gadgets and #Hacks you must try!!💩💩
00:49
Poly Holy Yow
Рет қаралды 23 МЛН
Spring по верхам: Тестирование REST-сервиса
44:32
Уголок сельского джависта
Рет қаралды 13 М.
Testcontainers  Интеграционные тесты для баз данных
15:39
Михаил Киселев
Рет қаралды 7 М.
5 советов на System Design Interview [SD]
17:10
Kirill Grishchuk - Software Engineer
Рет қаралды 2,1 М.
TESTING your SPRING DATA repositories
24:25
Pro Coder
Рет қаралды 6 М.
ТЕСТИРОВАНИЕ НА JAVA (JUNIT, MOCKITO)
9:14
Джавист
Рет қаралды 30 М.
Евгений Борисов - Spring - Глубоко и не очень
1:03:57
JPoint, Joker и JUG ru
Рет қаралды 158 М.
Я решал задачи 30 дней
6:37
Kirill Grishchuk - Software Engineer
Рет қаралды 1,7 М.
Java. Азы тестирования Mockito
28:47
Kirill Chokparov
Рет қаралды 36 М.
Survive 100 Days In Nuclear Bunker, Win $500,000
32:21
MrBeast
Рет қаралды 143 МЛН