Обновить
28
0.1

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

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

TL/DR. Единственная причина, почему нужно использовать Giga IDE 2025.1, а не Open IDE, исключительно в том, что она уже поддерживает 25 яву, чем, к сожалению, не может похвастать последняя версия Open IDE.

Идея в том, что фейк является полноценной (пусть и очень простой) имплементацией.

  • Если вдруг изменился вызываемый метод того же класса (который уже есть в интерфейсе), то фейк продолжит работать.

  • Если изменилась сигнатура метода - упадет билд с явной ошибкой, которую нужно поправить в 1 месте - фейке и она продолжит работать со всеми тестами.

Всё ровно так, как и в ситуации с моком.

юнит тест становится не юнитом

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

а пол слоя тестирует...

А вот это, конечно, плохо, очень плохо. Тестировать надо всё, а не половину.

у него не плохо получается)

Ничем не лучше, но и не хуже моков.

Да, практически, все, возникающие при изменениях pom-ника не в IDE, например, при активном переключении веток в git, особенно, если переключаться не в IDE.

  1. Изменения в зависимостях IDE просто "не видит" даже через "Reload All...", т.е. мавеном я собрать могу, а в IDE классы красные, потому что какие-то зависимости перестали разрешаться. Причём бывает по-разному: и новые классы могут не видеться, и старые, но с обновлённой версией, перестали. С вашим плагином ни разу не было проблем. "Reload All..." - решает все проблеы.

  2. Иногда 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 с нужными значениями атрибутов?

`when`(userRepository.findById(userId)).thenReturn(mockUser)
`when`(productRepository.findById(productId)).thenReturn(mockProduct)
`when`(promoService.validatePromo(promoCode, Category.ELECTRONICS)).thenReturn(true)
`when`(promoService.calculateDiscount(promoCode, Money(1000.0))).thenReturn(Money(200.0))

Наличие подобного - признак хренового теста. Моки в тестах должны принадлежать к одному слоою. А тут, очевидно, и слой хранения, и слой бизнес-логики. Т.е. это тест ради теста, а не для проверки функционала. Такое имеет право на существование исключительно редких случаях легаси-проектов, когда включают проверки на минимальное покрытие тестами, а тестов нет вообще. Но это техдолг с рождения, который должен быть переписан.

Уж лучше никаких тестов, чем такие. Так хотя бы не появляется иллюзии, что ты что-то контролируешь.

обязательный afterEach/beforeEach

Достаточно сделать их в базовом классе.

Выглядит как набор костылей,

Моки - это в принципе костыли для тестов.

Преогромнейшее спасибо за такой плагин.

С самого начала было понятно, что проблема возникает из-за порядка выполнения тестов. А вот это стало возможно в принципе потому, что инструмент используется, а пользоваться им правильно никто не удосужился (не "не умеет"!!!). Подобные проблемы решаются простым @AfterEach-методом, в котором все моки передаются в verifyNoMoreInteractions(). Опционально, можно добавить @BeforeEach с reset()-ом.

Всё, проблема финито. Если в каком-то тесте вызов мока не провалидирован - это херовый тест. Потому что он завязан (пусть даже неявно) на мок, но эту завязку не проверяет.

Ну, и вдобавок каждый тест с @Mock-ом - это отдельный спринговый контекст, который надо поднять. А это время, и, порой, немалое. Поэтому все моки, если они вообще нужны, должны быть определены в одном базовом тестовом классе, от которого будут наследоваться другие. Иначе на 2 секунды тестов, по 10 секунд на запуск контекстов будет уходить.

  1. Ключевое слово - "иногда". Конкретно в обсуждаемом случае, не та ситуация.

  2. И ретраи, и кэширование тоже надо проверять. Хотя бы для того, чтобы понимать, что настроил их правильно.

Ещё раз, я не говорю, что полный аналог прода нужно запускать всегда, но минимальные happycase-ы проверять надо. Потому что банальная опечатка в имени свойства в лучшем случае приведёт к падению при разворачивании приложения на стенде, а если нет?
Приложение поднялось, как-то работает, а потом выясняется, что, например, конфиг для таймаута запроса в третьестороннюю систему вообще не задан. Вернее, ты думал, что задал, но ошибся в имени. И таймаут вечный. И всё, и привет. Причём, если на тестовых стендах эта третья сторона эмулируется, то о бесконечном таймауте мы можем узнать только на проде.

За чем

Зочем, жы.

Есть юнит тесты

Согласен. Но в данном случае, кэш-менеджер - это осознанно добавленная зависимость. Соответственно, она должна быть протестирована. Возможно, не эти тесты (с поднятием всех нужных зависимостей) могут быть неполными и покрывать только happycase, но они должны быть. Иначе можно вообще все интеграции NoOp-моками заменить. Просто чтобы тесты позеленить.

Для тестов подойдёт даже простой NoOpCacheManager

Нет, не подойдёт. Нахрена нужен тест, который тестирует совершенно не то окружение, в котором предполагается работа?

Подводный камень: если внедрить Prototype внутрь Singleton, Spring создаст только один экземпляр при создании Singleton, а не новый каждый раз.

Новый объект будет создаваться именно каждый раз, когда бин запрашивается из контекста. А то, что для кого-то оказывается сюрпризом, что создание и, соответственно, инъекция зависимостей синглтона - единоразовая акция, тут уж, извините, ой.

Ну, и вообще это не проблема. Т.к. инъектируемая прокся просто создаёт новый экземпляр на каждый вызов метода. Правда, для этого контекст нужно настраивать, а не настройки по умолчанию использовать.

чтобы ради одного клиента менеджер открыл офис раньше времени.

А на кой для всего описанного открывать офис, если всё это спокойно делается через приложение?

Детишки разрушают дом старой одинокой женщины, а её саму сжигают в печи, например.

Тот факт, что вы сейчас написали этот комментарий, таки полностью опровергает ваше утверждение.

Вообще-то этого требует SQL-стандарт. Остальное - лишь следствие следования этому стандарту различными СУБД.

Ошейник эффектнее.

private static final SimpleDateFormat FORMATTER

Т.е. работа в многопоточном окружении не предусматривается?

new Date(time + LENGTH_OF_DAY)

Вот бы было бы удобно, если бы в стандартной библиотеке был какой-нибудь тип, позволяющий работать с датами без подобного геморроя, правда?

И да, использование timestamp в postgresql - моветон.

при любом снятии автомобиля с "линии" - он не приносит дохода, обычно это называется "упущенная выгода"

А вы, немного притерев бампер, на эвакуаторе авто в покраску повезёте? Какое может быть снятие с линии из-за притёртости? Обязательно снятие с линии - это что-то из приложения к ПДД "Перечень неисправностей и условий, при которых запрещается эксплуатация транспортных средств". Что-то вне этого перечня уже блажь сервиса, который почему-то не хочет, чтобы авто приносил доход.

1
23 ...

Информация

В рейтинге
3 822-й
Откуда
Омск, Омская обл., Россия
Зарегистрирован
Активность