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

  Рет қаралды 15,536

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 - Планы про нагрузочное тестирование

Пікірлер: 62
@kirya522-dev
@kirya522-dev Жыл бұрын
Telegram канал с анонсами, обсуждениями, вопросами по видео. t.me/kirya522
@user-uw7zl3gm5r
@user-uw7zl3gm5r Жыл бұрын
спасибо большое за видео,приятно смотреть и слушать😃
@faniskhalikov9736
@faniskhalikov9736 11 ай бұрын
Спасибо! Концентрация полезности зашкаливает )) Как раз то, что мне нужно для пэт-проекта!
@crew534
@crew534 Жыл бұрын
Прекрасное видео, очень хорошая подача, благодарю за помощь
@user-de4oq1uu9h
@user-de4oq1uu9h 7 ай бұрын
Спасибо большое, очень много интересного узнал! Круто!!
@DanChofire
@DanChofire 5 ай бұрын
Спасибо лектору, очень крутая подача и материал.
@raccoon8230
@raccoon8230 Жыл бұрын
Спасибо! Подача - 🔥
@alexidrlen1538
@alexidrlen1538 Жыл бұрын
Очень круто объясняете, спасибо большое!!!
@kirya522-dev
@kirya522-dev Жыл бұрын
Скоро сделаю по интеграционным тестам
@mustFLEXboi
@mustFLEXboi 8 ай бұрын
Спасибо. Очень полезно
@DuncanBatat
@DuncanBatat Жыл бұрын
Спасибо за видео! Очень помогло осознать цели юнит-тестов и начать разбираться с Moсkito.
@kirya522-dev
@kirya522-dev Жыл бұрын
Рад был помочь
@user-iu6yz6ck6h
@user-iu6yz6ck6h 2 жыл бұрын
Подписался на канал. Спасибо за видео )
@lexxx1994
@lexxx1994 2 жыл бұрын
годно 👏
@kifacapybara7309
@kifacapybara7309 5 ай бұрын
спасибо, очень полезно! ненавижу тестирование)
@alexeikopendakov3348
@alexeikopendakov3348 4 ай бұрын
Казалось бы банальщина, но очень нужная! Спасибо!
@69ultrapotato
@69ultrapotato Жыл бұрын
Юнит тесты спринг-бинов очень хрупки. Поменял тип/удалил одно поле в дто/сущности - 50 тестов сломалось. Добавил в сервис еще один бин. Он не замокан в 50 тестах - они сломались. И так до бесконечности. Юнитами например кастомные валидаторы отлично покрываются. К тому же куча всего юнитами просто не покрывается, потому что логика она в аннотациях, а не только в коде. Поэтому пишу интеграционные разного масштаба, а юниты только в крайнем случае, когда логика в одном методе сервиса очень заковыристая, и мокать надо не безумно много(но это обычно признак, что нужно выделить еще один сервис).
@kirya522-dev
@kirya522-dev Жыл бұрын
Есть аннотации для тестов по типу @mock и в итоге тесты расширяются без особых проблем
@kirya522-dev
@kirya522-dev Жыл бұрын
А тест на аннотацию и валидаторы можно написать один раз и их везде использовать
@alexanderkadatskiy7986
@alexanderkadatskiy7986 2 жыл бұрын
Привет! Отличное видео! А примера с интеграционными тестами с использованием спрингового контекста не планируется?
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Хотел сделать, но там гораздо больше надо рассказать. - mockmvc - конфиги - test containers
@alexanderkadatskiy7986
@alexanderkadatskiy7986 2 жыл бұрын
@@kirya522-dev Больше - не меньше) Можно на несколько видосов разбить
@TheLordGamesTv
@TheLordGamesTv 2 жыл бұрын
@@kirya522-dev + про интеграционные хотелось бы видео, ждем
@mr.whitesnow
@mr.whitesnow 4 ай бұрын
создавать тестовые данные в тесте - плохая практика, на мой взгляд например, у Вас тест проверяющий поиск по репе, в котором сначала Вы пишете в репу, а потом делаете по этим данным поиск а что если запись в репу не случилась, то упадет тест, который тестит поиск и в отчете будет видно что сломался поиск по репе, что не соответствует действительности и может быть принято неверное решение, например, о готовности релиза на мой взгляд, правильный подход - это когда тестовые данные уже готовы до начала выполнения теста, т.е. если мы тестируем поиск данных, то данные для этого поиска уже должны быть там
@kirya522-dev
@kirya522-dev 4 ай бұрын
Есть соглашение, что должно быть ровно наоборот. Тест создаёт данные и их же ищет, теперь вопрос почему. Потому что логика создания и наполнения данных тоже изменяется, программное управление созданием упрощает поддержку. А когда все данные есть и полное совпадение, это acceptance тестирование, самая дорогая часть пирамиды тестирования и самая не гибкая, нужна скорее в полноценных сценариях пользователя, а не в узких кусочках
@mr.whitesnow
@mr.whitesnow 4 ай бұрын
согласен, что не удобно управлять тестовыми данными но в вашем случает тест проверяет не только то, что должен и может упасть раньше сути тесткейса в итоге менеджер смотрит результат с системе отчетности и возможно принимает неверное решение я эт не придумал, это из реальной жизни пример 😊
@georgepro8481
@georgepro8481 2 жыл бұрын
Привет! Для 8й джавы сработает так же?
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Да, вроде бы все что рассказал работает на 8
@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 Жыл бұрын
Немного придерусь к вопросу: "тесты в проде" вообще не юзают, они прогоняются перед сборкой, а затем "вырезаются" из продового билда, они там уже не нужны)
@stepan-klyukin
@stepan-klyukin 2 ай бұрын
А что делать если в результате работы метода у обьекта должно измениться одно поле? Мокать все поля кроме этого поля и делать бва таких обьекта но разным значением этого поля?
@kirya522-dev
@kirya522-dev Ай бұрын
Сделать свойство и доступ через геттер и его мокнуть
@The_Vict0r
@The_Vict0r Жыл бұрын
Полезное видео, спасибо! А может EventBuilder лучше поместить на уровень сервисов? Это ведь уже работа с сущностями, а "контроллер должен быть тупым" :)
@kirya522-dev
@kirya522-dev Жыл бұрын
А тут получается разделение ответственности, что есть core сервисы которые работают с сущностями, а контроллер отвечает именно за их представление, но на практике чаще это выражается ещё в один сервис который называется Api и в нем логика и маппинг
@The_Vict0r
@The_Vict0r Жыл бұрын
@@kirya522-dev Ага. И этот Api находится в слое сервисов - я правильно понимаю?
@kirya522-dev
@kirya522-dev Жыл бұрын
Предлагаю перейти от слоев к мавен модулям, чтобы было понятнее. Есть соответственно модули: - сервисов - Api И логика маппинга находится в модуле Api на слое сервисов, надеюсь не слишком запутал
@The_Vict0r
@The_Vict0r Жыл бұрын
@@kirya522-dev Ну, я попробую понять )
@Das.Kleine.Krokodil
@Das.Kleine.Krokodil Жыл бұрын
Нужно ли как то тестировать репозиторий если в нем нет кода? по типу такого: @Repository public interface EmployeeRepository extends JpaRepository { }
@kirya522-dev
@kirya522-dev Жыл бұрын
фреймворки тестировать неблагородное дело
@SplashDmg2011
@SplashDmg2011 Жыл бұрын
Я бы сказал немного иначе: тестированием фреймворков должны заниматься создатели этих фреймворков, нам повторно это делать не нужно)
@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 Жыл бұрын
А нормально так контроллер тестировать, явно вызывая его методы? На проде так делаете, нет проблем? А то все материалы на которые натыкаюсь, используют @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 спасибо
@nickivanov7903
@nickivanov7903 2 жыл бұрын
контроллер можно было тестить через web mvc test
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Да, но так получится уже интеграционный тест с контекстом🙂
@alejandrospencio5524
@alejandrospencio5524 Жыл бұрын
а приватные методы вы проверяете ?
@kirya522-dev
@kirya522-dev Жыл бұрын
Приватные методы тестировать не надо, тестируется поведение публичных интерфейсов, приватные должны быть использованы в них и будут покрыты автоматически
@kirya522-dev
@kirya522-dev Жыл бұрын
Но иногда есть плохой код, который неудобно рефакторить, то private метод становится package-private с аннотацией @VisibleForTesting и тестируется отдельно
@alejandrospencio5524
@alejandrospencio5524 Жыл бұрын
@@kirya522-dev спасибо, не знал )
@alexricher2554
@alexricher2554 2 жыл бұрын
У тебя очень хорошо получается объяснять! Было бы круто, если бы ты сделал видео на тему: как запустить простейшее spring boot приложение с БД. А то уже пару дней маюсь, никак не получается: бд создаётся, а таблица нет. Мб скрипт надо какой закинуть, чтобы он при запуске контейнера создавал таблицу? Не знаешь, как это вообще делается?
@kirya522-dev
@kirya522-dev 2 жыл бұрын
Вообще несколько есть способов, самый простой liquibase
@zhennik263
@zhennik263 2 жыл бұрын
Ну самый простой вариант это заставить hibernate создавать таблицы. А нормальный вариант это да, liqibase
@alexricher2554
@alexricher2554 2 жыл бұрын
@@kirya522-dev эх, как давно это было. Уже работаю на позиции Джуна)
@user-gv3zn1us6s
@user-gv3zn1us6s 10 ай бұрын
Зачем людям видеть лицо лектора? Это отвлекает от кода. Непонятное самолюбование
@kirya522-dev
@kirya522-dev 10 ай бұрын
Кому-то наоборот важно видеть, под всех не подстроюсь
@user-gw6df6ns7e
@user-gw6df6ns7e 8 ай бұрын
Он художник, он так видит. Кто то любит, чтобы ролик не был обезличен. Кто то наоборот.
Spring Boot. JUnit 5. Пишем первый юнит-тест
20:30
小女孩把路人当成离世的妈妈,太感人了.#short #angel #clown
00:53
He sees meat everywhere 😄🥩
00:11
AngLova
Рет қаралды 6 МЛН
Is it Cake or Fake ? 🍰
00:53
A4
Рет қаралды 20 МЛН
Java Unit Testing with JUnit - Tutorial - How to Create And Use Unit Tests
21:35
Тестирование Flutter-приложений
1:17:26
Skill Branch
Рет қаралды 6 М.
Spring Data JPA Tutorial | Full In-depth Course
2:20:14
Daily Code Buffer
Рет қаралды 372 М.
Spring Boot Testing - ** Batteries Included 🔋🔋
41:12
Dan Vega
Рет қаралды 17 М.
ТЕСТИРОВАНИЕ НА JAVA (JUNIT, MOCKITO)
9:14
Джавист
Рет қаралды 27 М.
Вкатываемся в тестирование кода
8:35
ExtremeCode
Рет қаралды 128 М.
Spring Cloud goes Cloud
2:10:21
Aleksandr Barmin
Рет қаралды 32 М.
Main filter..
0:15
CikoYt
Рет қаралды 10 МЛН
How charged your battery?
0:14
V.A. show / Магика
Рет қаралды 7 МЛН
iPhone 12 socket cleaning #fixit
0:30
Tamar DB (mt)
Рет қаралды 49 МЛН