Семен Киреков - Spring Data JPA. Антипаттерны тестирования
Вставка
- Опубліковано 16 жов 2024
- Ближайшая конференция - Joker 2024, 9 октября (Online), 15-16 октября (Санкт-Петербург + трансляция).
Подробности и билеты: jrg.su/Ypf1HW
- -
За свою карьеру спикер столкнулся с рядом (а некоторые даже попробовал) антипаттернов тестирования при использовании Spring Data JPA. Они не только не помогают, но и усложняют поддержку кода и вызывают раздражение.
В рамках доклада Семен расскажет вам о таких антипаттернах, как избыточный coupling на декларацию сущностей, лишние зависимости, best practices для создания тестовых данных и транзакционные сценарии. А также покажет паттерны, на которые следует их заменить, чтобы упростить жизнь при написании тестов.
Скачать презентацию: squidex.jugru....
Используешь рандомайзер в тестах - получаешь тесты, которые рандомно либо проходят либо не проходят. Это тоже антипаттерн.
Очень полезный доклад, все по делу и применимо, спасибо!
Спасибо!
Доклад очень понравился, спасибо. + за интеграционные и End to End тесты.
Пример с проверкой статуса у робота, где exception прерывает транзакцию. Каждый раз, используя исключения для обработки штатных ситуаций я вижу с проблемы. Если это checked - не откатываются транзакции по умолчанию и нужно постоянно прописывать в сигнатуре по цепочке вызовов. Если unchecked - после рефакторинга может либо не хватить нового catch, либо останется старый мусорный. Я попробовал возвращать объект (статус + доп данные), обрабатывать через if или через switch (статус в enum и это гарантия перебора всех возможных ситуаций в клиентском коде). Это вполне решает задачу. Почему это не используется? Просто не java-style или этому есть еще какие-то причины?
Как я понял, ты говоришь про Either монаду, которая может вернуть либо ошибку, либо исключение. Думаю, проблема в том, что в Java нет (пока еще) прокаченного pattern matching. В Scala Either используется довольно часто, потому что язык позволяет деконструировать ее значение таким образом, что проверка всех возможных вариантов выполняется в compile time. В Java же можно, например, забыть проверить одно из условий и компилятор никак об этом не уведомит. Exception же в этом плане более безопасен. RuntimeException вылетел за границы transactional proxy? Ставим флаг rollback only.
Позволять-то он позволяет, но по умолчанию это warning (unexhaustive match в scala). И проектов, где это не перенастраивали хватает.
Спасибо за доклад.
Идея с @With отлично подходит для не больших entity(или дто, если более глобально смотреть на тесты), для больших сущность возможно удобнее передавать лямбду, которой менять дефолтные поля, т.к. это избавит от дублирования в тестбилдере большого кол-ва полей, в которых проще допустить ошибку
Спасибо!
Согласен по поводу больших сущностей. Вообще, мы в новом проекте сейчас пришли к концепции, что entity должна предоставлять статические методы для валидного создания этой самой entity. А AllArgs/NoArgs конструкторы не должны быть доступны из вне. В конце концов, в бизнес-коде не будет тест-билдеров. Так что используя в тестах лишь публичное API класса и скрывая все детали реализации внутри, мы не только конструируем валидные объекты с точки зрения домена, но и сразу тестируем те методы, которые и будут вызываться в коде приложения.
@@kirekov Добрый день. Под стат методами ентити вы имеете ввиду билдер? А конструктор ентити у вас private?
Спасибо за доклад. Применяю на практике )
Замах на рубль, удар на копейку
спасиб
"Ну и это довольно verbose". Тьфу.
В итоге что стоит использовать вместо @DirtyContext? @BeforeEach с repository.deleteAll()?
Лучше явно чистить БД перед тестами. Если использовать Testcontainers, то DirtiesContext вообще никак не поможет, потому что данные будут храниться не в памяти (i.e. в Spring Context), а в контейнере с БД