TL/DR. Единственная причина, почему нужно использовать Giga IDE 2025.1, а не Open IDE, исключительно в том, что она уже поддерживает 25 яву, чем, к сожалению, не может похвастать последняя версия Open IDE.
Идея в том, что фейк является полноценной (пусть и очень простой) имплементацией.
Если вдруг изменился вызываемый метод того же класса (который уже есть в интерфейсе), то фейк продолжит работать.
Если изменилась сигнатура метода - упадет билд с явной ошибкой, которую нужно поправить в 1 месте - фейке и она продолжит работать со всеми тестами.
Всё ровно так, как и в ситуации с моком.
юнит тест становится не юнитом
Юнит-тест и спринговый контекст - два непересекающихся множества, если новый контекст не поднимается на каждый тестовый метод. Но если так делать, то даже на средних проектах тесты будут выполняться до морковкиного заговения. Так никто в здравом уме делать не будет.
а пол слоя тестирует...
А вот это, конечно, плохо, очень плохо. Тестировать надо всё, а не половину.
Да, практически, все, возникающие при изменениях pom-ника не в IDE, например, при активном переключении веток в git, особенно, если переключаться не в IDE.
Изменения в зависимостях IDE просто "не видит" даже через "Reload All...", т.е. мавеном я собрать могу, а в IDE классы красные, потому что какие-то зависимости перестали разрешаться. Причём бывает по-разному: и новые классы могут не видеться, и старые, но с обновлённой версией, перестали. С вашим плагином ни разу не было проблем. "Reload All..." - решает все проблеы.
Иногда Maven Helper строит дерево не с теми версиями, которые разрешает мавен.
Проблема же, что они создают очень хрупкую тестовую систему основную скорее на вайтбоксе. Т.е. больше часть теста, на самом деле, не проверка выполнения, а проверка, что моки правильно сконфигурированы.
А фейковые заглушки, предлагаемые вами в статье, не на этом основаны? Просто моки более настраиваемы, могут быть переиспользованы в разных сценариях. И, опять же, использование моков должно иметь свои пределы.
val mockUser = mock<User> {
on { id } doReturn userId
on { status } doReturn UserStatus.ACTIVE
}
val mockProduct = mock<Product> {
on { id } doReturn productId
on { price } doReturn Money(1000.0)
on { category } doReturn Category.ELECTRONICS
}
Заставь дурака богу молиться, он и лоб расшибёт. (c) За такой "мокизм головного мозга" надо железной линейкой по пальцам. Почему эти объекты просто не создать через new с нужными значениями атрибутов?
Наличие подобного - признак хренового теста. Моки в тестах должны принадлежать к одному слоою. А тут, очевидно, и слой хранения, и слой бизнес-логики. Т.е. это тест ради теста, а не для проверки функционала. Такое имеет право на существование исключительно редких случаях легаси-проектов, когда включают проверки на минимальное покрытие тестами, а тестов нет вообще. Но это техдолг с рождения, который должен быть переписан.
Уж лучше никаких тестов, чем такие. Так хотя бы не появляется иллюзии, что ты что-то контролируешь.
С самого начала было понятно, что проблема возникает из-за порядка выполнения тестов. А вот это стало возможно в принципе потому, что инструмент используется, а пользоваться им правильно никто не удосужился (не "не умеет"!!!). Подобные проблемы решаются простым @AfterEach-методом, в котором все моки передаются в verifyNoMoreInteractions(). Опционально, можно добавить @BeforeEach с reset()-ом.
Всё, проблема финито. Если в каком-то тесте вызов мока не провалидирован - это херовый тест. Потому что он завязан (пусть даже неявно) на мок, но эту завязку не проверяет.
Ну, и вдобавок каждый тест с @Mock-ом - это отдельный спринговый контекст, который надо поднять. А это время, и, порой, немалое. Поэтому все моки, если они вообще нужны, должны быть определены в одном базовом тестовом классе, от которого будут наследоваться другие. Иначе на 2 секунды тестов, по 10 секунд на запуск контекстов будет уходить.
Ключевое слово - "иногда". Конкретно в обсуждаемом случае, не та ситуация.
И ретраи, и кэширование тоже надо проверять. Хотя бы для того, чтобы понимать, что настроил их правильно.
Ещё раз, я не говорю, что полный аналог прода нужно запускать всегда, но минимальные happycase-ы проверять надо. Потому что банальная опечатка в имени свойства в лучшем случае приведёт к падению при разворачивании приложения на стенде, а если нет? Приложение поднялось, как-то работает, а потом выясняется, что, например, конфиг для таймаута запроса в третьестороннюю систему вообще не задан. Вернее, ты думал, что задал, но ошибся в имени. И таймаут вечный. И всё, и привет. Причём, если на тестовых стендах эта третья сторона эмулируется, то о бесконечном таймауте мы можем узнать только на проде.
Согласен. Но в данном случае, кэш-менеджер - это осознанно добавленная зависимость. Соответственно, она должна быть протестирована. Возможно, не эти тесты (с поднятием всех нужных зависимостей) могут быть неполными и покрывать только happycase, но они должны быть. Иначе можно вообще все интеграции NoOp-моками заменить. Просто чтобы тесты позеленить.
Подводный камень: если внедрить Prototype внутрь Singleton, Spring создаст только один экземпляр при создании Singleton, а не новый каждый раз.
Новый объект будет создаваться именно каждый раз, когда бин запрашивается из контекста. А то, что для кого-то оказывается сюрпризом, что создание и, соответственно, инъекция зависимостей синглтона - единоразовая акция, тут уж, извините, ой.
Ну, и вообще это не проблема. Т.к. инъектируемая прокся просто создаёт новый экземпляр на каждый вызов метода. Правда, для этого контекст нужно настраивать, а не настройки по умолчанию использовать.
при любом снятии автомобиля с "линии" - он не приносит дохода, обычно это называется "упущенная выгода"
А вы, немного притерев бампер, на эвакуаторе авто в покраску повезёте? Какое может быть снятие с линии из-за притёртости? Обязательно снятие с линии - это что-то из приложения к ПДД "Перечень неисправностей и условий, при которых запрещается эксплуатация транспортных средств". Что-то вне этого перечня уже блажь сервиса, который почему-то не хочет, чтобы авто приносил доход.
TL/DR. Единственная причина, почему нужно использовать Giga IDE 2025.1, а не Open IDE, исключительно в том, что она уже поддерживает 25 яву, чем, к сожалению, не может похвастать последняя версия Open IDE.
Всё ровно так, как и в ситуации с моком.
Юнит-тест и спринговый контекст - два непересекающихся множества, если новый контекст не поднимается на каждый тестовый метод. Но если так делать, то даже на средних проектах тесты будут выполняться до морковкиного заговения. Так никто в здравом уме делать не будет.
А вот это, конечно, плохо, очень плохо. Тестировать надо всё, а не половину.
Ничем не лучше, но и не хуже моков.
Да, практически, все, возникающие при изменениях pom-ника не в IDE, например, при активном переключении веток в git, особенно, если переключаться не в IDE.
Изменения в зависимостях IDE просто "не видит" даже через "Reload All...", т.е. мавеном я собрать могу, а в IDE классы красные, потому что какие-то зависимости перестали разрешаться. Причём бывает по-разному: и новые классы могут не видеться, и старые, но с обновлённой версией, перестали. С вашим плагином ни разу не было проблем. "Reload All..." - решает все проблеы.
Иногда Maven Helper строит дерево не с теми версиями, которые разрешает мавен.
А фейковые заглушки, предлагаемые вами в статье, не на этом основаны? Просто моки более настраиваемы, могут быть переиспользованы в разных сценариях. И, опять же, использование моков должно иметь свои пределы.
Заставь дурака богу молиться, он и лоб расшибёт. (c) За такой "мокизм головного мозга" надо железной линейкой по пальцам. Почему эти объекты просто не создать через
newс нужными значениями атрибутов?Наличие подобного - признак хренового теста. Моки в тестах должны принадлежать к одному слоою. А тут, очевидно, и слой хранения, и слой бизнес-логики. Т.е. это тест ради теста, а не для проверки функционала. Такое имеет право на существование исключительно редких случаях легаси-проектов, когда включают проверки на минимальное покрытие тестами, а тестов нет вообще. Но это техдолг с рождения, который должен быть переписан.
Уж лучше никаких тестов, чем такие. Так хотя бы не появляется иллюзии, что ты что-то контролируешь.
Достаточно сделать их в базовом классе.
Моки - это в принципе костыли для тестов.
Преогромнейшее спасибо за такой плагин.
С самого начала было понятно, что проблема возникает из-за порядка выполнения тестов. А вот это стало возможно в принципе потому, что инструмент используется, а пользоваться им правильно никто не удосужился (не "не умеет"!!!). Подобные проблемы решаются простым
@AfterEach-методом, в котором все моки передаются вverifyNoMoreInteractions(). Опционально, можно добавить@BeforeEachсreset()-ом.Всё, проблема финито. Если в каком-то тесте вызов мока не провалидирован - это херовый тест. Потому что он завязан (пусть даже неявно) на мок, но эту завязку не проверяет.
Ну, и вдобавок каждый тест с
@Mock-ом - это отдельный спринговый контекст, который надо поднять. А это время, и, порой, немалое. Поэтому все моки, если они вообще нужны, должны быть определены в одном базовом тестовом классе, от которого будут наследоваться другие. Иначе на 2 секунды тестов, по 10 секунд на запуск контекстов будет уходить.Ключевое слово - "иногда". Конкретно в обсуждаемом случае, не та ситуация.
И ретраи, и кэширование тоже надо проверять. Хотя бы для того, чтобы понимать, что настроил их правильно.
Ещё раз, я не говорю, что полный аналог прода нужно запускать всегда, но минимальные happycase-ы проверять надо. Потому что банальная опечатка в имени свойства в лучшем случае приведёт к падению при разворачивании приложения на стенде, а если нет?
Приложение поднялось, как-то работает, а потом выясняется, что, например, конфиг для таймаута запроса в третьестороннюю систему вообще не задан. Вернее, ты думал, что задал, но ошибся в имени. И таймаут вечный. И всё, и привет. Причём, если на тестовых стендах эта третья сторона эмулируется, то о бесконечном таймауте мы можем узнать только на проде.
Зочем, жы.
Согласен. Но в данном случае, кэш-менеджер - это осознанно добавленная зависимость. Соответственно, она должна быть протестирована. Возможно, не эти тесты (с поднятием всех нужных зависимостей) могут быть неполными и покрывать только happycase, но они должны быть. Иначе можно вообще все интеграции NoOp-моками заменить. Просто чтобы тесты позеленить.
Нет, не подойдёт. Нахрена нужен тест, который тестирует совершенно не то окружение, в котором предполагается работа?
Новый объект будет создаваться именно каждый раз, когда бин запрашивается из контекста. А то, что для кого-то оказывается сюрпризом, что создание и, соответственно, инъекция зависимостей синглтона - единоразовая акция, тут уж, извините, ой.
Ну, и вообще это не проблема. Т.к. инъектируемая прокся просто создаёт новый экземпляр на каждый вызов метода. Правда, для этого контекст нужно настраивать, а не настройки по умолчанию использовать.
А на кой для всего описанного открывать офис, если всё это спокойно делается через приложение?
Детишки разрушают дом старой одинокой женщины, а её саму сжигают в печи, например.
Тынц.
Тот факт, что вы сейчас написали этот комментарий, таки полностью опровергает ваше утверждение.
Вообще-то этого требует SQL-стандарт. Остальное - лишь следствие следования этому стандарту различными СУБД.
И чёрно-белые списки
Ошейник эффектнее.
Т.е. работа в многопоточном окружении не предусматривается?
Вот бы было бы удобно, если бы в стандартной библиотеке был какой-нибудь тип, позволяющий работать с датами без подобного геморроя, правда?
И да, использование
timestampв postgresql - моветон.А вы, немного притерев бампер, на эвакуаторе авто в покраску повезёте? Какое может быть снятие с линии из-за притёртости? Обязательно снятие с линии - это что-то из приложения к ПДД "Перечень неисправностей и условий, при которых запрещается эксплуатация транспортных средств". Что-то вне этого перечня уже блажь сервиса, который почему-то не хочет, чтобы авто приносил доход.