Как мне кажется, Вы наилучше объяснили тестирование REST-сервиса; сколько пересмотрел видео - все не то, но именно Ваша дикция, подача материала и что самое главное, и просто элементарное - очень мало воды, заинтересовали меня подписаться на Вас и углублять свои знания именно на Вашем канале! Спасибо за Ваш труд!!!
случайно попалось это видео как раз в тот момент, когда оно было максимально нужно. Отличная подача материала, очень крутой видеоролик, буду ждать следующих уроков!
Спасибо за видео, в связке с книгой «Спринг быстро» самое то! Позвольте задать вопрос. Год работаю java разработчиком, по стеку нету спринга, хибернейта. Насколько мне будет тяжело найти работу на спринговый стек (с кафкой, хибернейтом, микросервисы желательно)? При самостоятельном изучении. Могу ли я на собесах говорить что у нас был спринг? Как мне лушче поступить?
В AssertJ, на мой взгляд, unit-тесты выглядят по-красивее, плюс текстовые блоки не требуют ставить закрывающие три кавычки на новой строке - чаще всего удобнее ставить их в конце предыдущей строки - для экономии места.
Ну так и ролик не про AssertJ, а про Spring и "по верхам", так-то много всего можно добавить, что используется в реальных условиях) Ну, а новая строка в конце текстового блока - не более, чем привычка.
Здравствуйте, отличная подача материала у Вас , усваивается быстро. Но есть один вопрос : Делал всё как у Вас , но почему то тесты не покрывают методы в контроллере, выделены красными. И еще переменная MockMvc mockMvc подчеркнута красным , хотя импорт тот же. Но на работу тестов не влияет. Не подскажете почему?
Спасибо за комментарий) Визуализация покрытия кода тестами зависит от конкретной IDE и её настроек. Например, в IDEA можно при тестировании указывать какие классы или пакеты, для которых должно анализироваться покрытие кода, возможно целевой класс исключён из этого списка. Свойство MockMvc, скорее всего, подчёркнуто красным из-за того, что IDE не может определить, каким образом это свойство должно быть проинициализировано. Причин для такого поведения может быть много.
Спасибо за лекцию! Узнал несколько новых паттернов написания кода. Очень интересно и подробно рассказываете. Хотел спросить - зачем при обращению к полю класса Вы всегда делаете это через this, когда можно обратиться напрямую? ("...when(this.taskRepository)... " , а не "...when(taskRepository)..." ? Вроде бы никакой ambiguity не наблюдается? Спасибо заранее за ответ!
Приветствую! Спасибо за видео Буду признателен, если подскажете ответ на мой вопрос Если мой контроллер возвращает не респонсЕнтити а кастомный класс, как в таком случае получать боди, медиатайп и тому подобное ?
Получать или задавать? Если получать, то где? Если задавать, то "боди" - это то, что возвращается из метода, отмеченного аннотацией @ResponseBody, или в классе, отмеченном аннотацией @RestController, "медиатайп" можно указывать в аннотации @RequestMapping (и иже с ней, вроде @GetMapping и т.д.) параметром produces, например
@@shurik_codes не совсем то, что я имел ввиду ) В видео при написании текстов, мы проверяем статус ответа, проверяем Боди, а получаем эти значения с помощью методов responceEntity Если метод моего контроллера возвращает не responseEnity, а например мной написанный класс productResponce, и у него конечно же нет методов getBody и getHeaders, как тогда в таком случае я могу получить эти значения ? Спасибо за ответ !
Если речь о модульных тестах, то нужно проверять только ответ от метода, остальное - можно проверить в интеграционных тестах. Пытаться проверить это в модульных тестах нет смысла, т.к. та логика проверена разработчиками Spring Framework,
@@shurik_codesА еще можно вас спросить ?) Я сам искал и не нашел… Или может не понимаю Например я тестирую сервисный слой, в нем есть репозиторий и маппер Интерфейс репо я мокаю, а мапер я так понимаю нужен «оригинальный» объект, но совсем не понимаю как его туда добавить, учитывая что это интерфейс, пытался делать @spy , но всеровно не работало как должно.. Спасибо заранее за ответ )
Здравствуйте,Александр. Не могу понять зачем в методе handleCreateNewTask_PayloadIsValid_ReturnsValidResponseEntity блок else,он же никогда не выполнится,так как это то же самое, что в if
может быть не очевиден,но я вот что не понимаю. в if проверяется что getbody инстанс Task,но если у нас не зайдет в if,то какой смысл от else если мы в assertinstanceof проверяем то же условие что и в if. Или я вообще неправильно понимаю, или это для того чтобы тест не прошел в else и мы это поняли @@shurik_codes
А мне непонятно, если у Task будет добавлено новое свойство, например "просрочена", то тогда надо дописывать метод-тест корректного добавления task'a, проверяя, что "просрочена" = Ложь? Мне кажется это неправильно. И проверку на заполненость id и completed надо делать в рамках теста класса Task
Если новое свойство будет влиять на поток исполнения кода, допустим, валидироваться (например, нельзя создавать просроченные задачи), то это должно быть протестировано однозначно. Однако писать для этого отдельный метод не надо, это можно протестировать в handleCreateNewTask_PayloadIsValid_ReturnsValidResponseEntity и handleCreateNewTask_PayloadIsInvalid_ReturnsValidResponseEntity. Для Task в целом тесты писать нет смысла, т.к. это DTO и своей логики у него немного, да и вся она находится в конструкторе, который в рамках теста вызывается, следовательно, покрыт тестами.
Я просто делал dTOшку отдельно и потом через objectMapper подставлял, мне казалось это лаконичней, чем каждый раз писать JSONку в тесте, но наверно ты для наглядности делаешь
На самом деле нет, я на практике контрольное значение описываю именно в формате JSON. Использование каких-то DTO приводит к зависимости интеграционных тестов от этих самых DTO, что может повышать хрупкость тестов (интеграционные тесты и так по своей природе более хрупкие, чем модульные). То же самое касается и библиотек для сериализации (Jackson, GSON и т.д.). Более того, я практикую разработку через тестирование и на момент написания интеграционного теста соответствующий класс DTO может не существовать, в отличие от контракта.
@@shurik_codes Привет, мне кажется что дто как раз соответствует контракту, поменяется контракт, тогда поменяем и дто (ИТ зависит от контракта) Про не существующую реализацию тоже не очень понятно, когда мы практикуем тдд, то никакая реализация не существует(на момент создания теста). Что тогда мешает нажать пару клавиш и сгенерировать дто? По мне так, верифи больше связывает код и тесты, потому что мы начинаем тестировать SUT как белый ящик И в противовес тому что все ИТ очень хрупкие - некоторые ИТ можно свести к приемочным тестам которые тестируют поведение системы, им все равно на имплиментацию, что делает их самыми устойчивыми(ведь они зависят только от контракта). Типичный цикл ATDD - пишем приемочный тест охватывающий некоторую фичу, после этого используем короткие тдд циклы пока приемочный тест не пройдет. Такой ATDD цикл может начинаться с написания теста на какой-то эндпонит, а после нам нужно будет настроить некоторую инфраструктуру для его выполнения Вот, я не пытался задушнить, просто буду рад пообщаться на тему тестов и разработки через них А вообще, братан, харош! Давай-давай, вперед! Контент в кайф! Можно еще? Ваще красавчик! Можно вот этого вот почаще? Давайте пока! ПС очень понравился видос про TC и спринг бут 3.1
Это нормально, что для импорта doReturn() - пришлось вручную прописать import static org.mockito.Mockito.doReturn; ? Не как обычно при наборе метода автоимпорт... У меня IDEA Ultimate
А вот и текстовая версия alexkosarev.name/2022/12/29/spring-in-a-nutshell-testing-rest-services/
вижу твоё видео - автоматически ставлю лайк и пишу коммент! как всегда отличный материал👍
Как мне кажется, Вы наилучше объяснили тестирование REST-сервиса; сколько пересмотрел видео - все не то, но именно Ваша дикция, подача материала и что самое главное, и просто элементарное - очень мало воды, заинтересовали меня подписаться на Вас и углублять свои знания именно на Вашем канале!
Спасибо за Ваш труд!!!
Люблю смотреть ваши видео ❤❤❤🔥🔥🔥
Подача материала просто восхищает! Все понятно и по делу, спасибо за ваш труд!!!
Коротко, ясно, всё "по делу", без воды. Можно использовать не только как обучающее, но и справочный материал по ряду вещей.
Огромное спасибо!
ОМГ!!! Дикция, подача материала...да тут все прям на высоте! Продолжайте, пожалуйста, просто супер!
С удовольствием смотрю! Продолжай, пожалуйста! Хотелось бы курс полный посмотреть! И даже в деталях!
Отличная подача материала. Благодарность.
Я обалдел когда нашёл твою ютуб после того как использовал твой сайт. Ты молодец! Спасибо!
Полезный ролик, спасибо!
круто, реально круто. спасибо за полезный контент!
Очень круто! Спасибо
Шикарно! Вот бы авторы фреймворков документацию так писали!
случайно попалось это видео как раз в тот момент, когда оно было максимально нужно. Отличная подача материала, очень крутой видеоролик, буду ждать следующих уроков!
вообще крутая подача и объяснение
Спасибо за видео, все понятно)
Очень достойно! Продолжай пожайлуста
Спасибо большое за ваш труд
Отличная подача материала. Так держать!
спасибо!
Спасибо!
Очень познавательно спасибо!!!
незаслуженно мало просмотров и лайков. Контент пушка🔥
Отличная подача материала. Будет замечательно, если вы будете прописывать на экране горячие клавиши, которые используете. Ждем более сложных тем :)
Хоткеи я не буду показывать, в этом нет смысла, т.к. у меня нестандартная для IDEA раскладка)
Спасибо за видео, в связке с книгой «Спринг быстро» самое то!
Позвольте задать вопрос. Год работаю java разработчиком, по стеку нету спринга, хибернейта. Насколько мне будет тяжело найти работу на спринговый стек (с кафкой, хибернейтом, микросервисы желательно)? При самостоятельном изучении. Могу ли я на собесах говорить что у нас был спринг? Как мне лушче поступить?
В AssertJ, на мой взгляд, unit-тесты выглядят по-красивее, плюс текстовые блоки не требуют ставить закрывающие три кавычки на новой строке - чаще всего удобнее ставить их в конце предыдущей строки - для экономии места.
Ну так и ролик не про AssertJ, а про Spring и "по верхам", так-то много всего можно добавить, что используется в реальных условиях)
Ну, а новая строка в конце текстового блока - не более, чем привычка.
Всегда боялся тестов и обходил их стороной) Оказалось не так страшен чёрт)
Здравствуйте, отличная подача материала у Вас , усваивается быстро. Но есть один вопрос : Делал всё как у Вас , но почему то тесты не покрывают методы в контроллере, выделены красными. И еще переменная MockMvc mockMvc подчеркнута красным , хотя импорт тот же. Но на работу тестов не влияет. Не подскажете почему?
Спасибо за комментарий) Визуализация покрытия кода тестами зависит от конкретной IDE и её настроек.
Например, в IDEA можно при тестировании указывать какие классы или пакеты, для которых должно анализироваться покрытие кода, возможно целевой класс исключён из этого списка.
Свойство MockMvc, скорее всего, подчёркнуто красным из-за того, что IDE не может определить, каким образом это свойство должно быть проинициализировано. Причин для такого поведения может быть много.
Как -то решили свою проблему? Сейчас дошла до этой темы и вторые сутки ищу причину покраснений😊
@@india23061974 а зачем её решать?
Спасибо за лекцию! Узнал несколько новых паттернов написания кода. Очень интересно и подробно рассказываете. Хотел спросить - зачем при обращению к полю класса Вы всегда делаете это через this, когда можно обратиться напрямую? ("...when(this.taskRepository)... " , а не "...when(taskRepository)..." ? Вроде бы никакой ambiguity не наблюдается? Спасибо заранее за ответ!
Для повышения уровня читаемости кода. Когда видишь this, сразу понимаешь, что обращение идёт к свойству или методу класса.
@@shurik_codesПонял. Спасибо!
отличное руководство! где в идее настроить что бы такие же логи по тестам выводились, а то у меня вообще ничего в консоли не пишется?
27:50
@@shurik_codes спасибо за быстрый ответ, но аннотация есть, а логов нет. Выводится только инфа в три сточки про mock и servlet и все
Приветствую!
Спасибо за видео
Буду признателен, если подскажете ответ на мой вопрос
Если мой контроллер возвращает не респонсЕнтити а кастомный класс, как в таком случае получать боди, медиатайп и тому подобное ?
Получать или задавать? Если получать, то где? Если задавать, то "боди" - это то, что возвращается из метода, отмеченного аннотацией @ResponseBody, или в классе, отмеченном аннотацией @RestController, "медиатайп" можно указывать в аннотации @RequestMapping (и иже с ней, вроде @GetMapping и т.д.) параметром produces, например
@@shurik_codes не совсем то, что я имел ввиду )
В видео при написании текстов, мы проверяем статус ответа, проверяем Боди, а получаем эти значения с помощью методов responceEntity
Если метод моего контроллера возвращает не responseEnity, а например мной написанный класс productResponce, и у него конечно же нет методов getBody и getHeaders, как тогда в таком случае я могу получить эти значения ?
Спасибо за ответ !
Если речь о модульных тестах, то нужно проверять только ответ от метода, остальное - можно проверить в интеграционных тестах. Пытаться проверить это в модульных тестах нет смысла, т.к. та логика проверена разработчиками Spring Framework,
@@shurik_codes спасибо ☺️
@@shurik_codesА еще можно вас спросить ?)
Я сам искал и не нашел…
Или может не понимаю
Например я тестирую сервисный слой, в нем есть репозиторий и маппер
Интерфейс репо я мокаю, а мапер я так понимаю нужен «оригинальный» объект, но совсем не понимаю как его туда добавить, учитывая что это интерфейс, пытался делать @spy , но всеровно не работало как должно..
Спасибо заранее за ответ )
Здравствуйте,Александр. Не могу понять зачем в методе handleCreateNewTask_PayloadIsValid_ReturnsValidResponseEntity блок else,он же никогда не выполнится,так как это то же самое, что в if
Со стороны теста ответ не очевиден, поэтому есть проверка. Но вообще это плохой пример, в тестах недопустимы ветвления
может быть не очевиден,но я вот что не понимаю. в if проверяется что getbody инстанс Task,но если у нас не зайдет в if,то какой смысл от else если мы в assertinstanceof проверяем то же условие что и в if. Или я вообще неправильно понимаю, или это для того чтобы тест не прошел в else и мы это поняли @@shurik_codes
Хоть кто-то хорошо рассказывает за тесты
А мне непонятно, если у Task будет добавлено новое свойство, например "просрочена", то тогда надо дописывать метод-тест корректного добавления task'a, проверяя, что "просрочена" = Ложь?
Мне кажется это неправильно. И проверку на заполненость id и completed надо делать в рамках теста класса Task
Если новое свойство будет влиять на поток исполнения кода, допустим, валидироваться (например, нельзя создавать просроченные задачи), то это должно быть протестировано однозначно. Однако писать для этого отдельный метод не надо, это можно протестировать в handleCreateNewTask_PayloadIsValid_ReturnsValidResponseEntity и handleCreateNewTask_PayloadIsInvalid_ReturnsValidResponseEntity.
Для Task в целом тесты писать нет смысла, т.к. это DTO и своей логики у него немного, да и вся она находится в конструкторе, который в рамках теста вызывается, следовательно, покрыт тестами.
Я просто делал dTOшку отдельно и потом через objectMapper подставлял, мне казалось это лаконичней, чем каждый раз писать JSONку в тесте, но наверно ты для наглядности делаешь
На самом деле нет, я на практике контрольное значение описываю именно в формате JSON. Использование каких-то DTO приводит к зависимости интеграционных тестов от этих самых DTO, что может повышать хрупкость тестов (интеграционные тесты и так по своей природе более хрупкие, чем модульные). То же самое касается и библиотек для сериализации (Jackson, GSON и т.д.). Более того, я практикую разработку через тестирование и на момент написания интеграционного теста соответствующий класс DTO может не существовать, в отличие от контракта.
@@shurik_codes
Привет, мне кажется что дто как раз соответствует контракту, поменяется контракт, тогда поменяем и дто (ИТ зависит от контракта)
Про не существующую реализацию тоже не очень понятно, когда мы практикуем тдд, то никакая реализация не существует(на момент создания теста). Что тогда мешает нажать пару клавиш и сгенерировать дто?
По мне так, верифи больше связывает код и тесты, потому что мы начинаем тестировать SUT как белый ящик
И в противовес тому что все ИТ очень хрупкие - некоторые ИТ можно свести к приемочным тестам которые тестируют поведение системы, им все равно на имплиментацию, что делает их самыми устойчивыми(ведь они зависят только от контракта). Типичный цикл ATDD - пишем приемочный тест охватывающий некоторую фичу, после этого используем короткие тдд циклы пока приемочный тест не пройдет. Такой ATDD цикл может начинаться с написания теста на какой-то эндпонит, а после нам нужно будет настроить некоторую инфраструктуру для его выполнения
Вот, я не пытался задушнить, просто буду рад пообщаться на тему тестов и разработки через них
А вообще, братан, харош! Давай-давай, вперед! Контент в кайф! Можно еще? Ваще красавчик! Можно вот этого вот почаще? Давайте пока!
ПС очень понравился видос про TC и спринг бут 3.1
Это нормально, что для импорта doReturn() - пришлось вручную прописать import static org.mockito.Mockito.doReturn; ? Не как обычно при наборе метода автоимпорт... У меня IDEA Ultimate
Это было сделано для наглядности, чтобы показать, откуда импортируется метод
Я имею ввиду у себя при попытке повторить. Пришлось импортировать вручную...
@@karomag ну вообще - нет, это не нормально, автоимпорт должен срабатывать. У меня IDEA тупит только на MockMvcRequestBuilders.get
Вашу ж Машу!!! Автор хоть когда нибудь ошибается???
Бывает
здксь есть много огрехов
Автор, без обид конечно, название лучше поменять. Так и хотелось пролистать дальше. Примите это не в упрек и не замечание просто пожелание
Да без обид, конечно, а можно конкретнее, что с названием не так?