Конспект і таймкоди
0:00
JSON structure і межі raw strings
Raw JSON у Java string швидко стає незручним для large/nested payload і parameterization. JSON file у resources є кращим temporary step, але typed object дає compile-time names/types і IDE support.
Розбираються objects, arrays, values, nested arrays і відмінності JSON від XML-style wrappers. Модель має повторювати actual wire shape, а не вигадану class hierarchy.
20:00
POJO generation і Jackson mapping
POJO описує fields, accessors, equality/hash і string representation. Моделі можна згенерувати з real JSON через jsonschema2pojo або RoboPOJOGenerator, обравши Jackson annotations і, за потреби, Lombok.
@JsonProperty зв’язує JSON name з Java field, Jackson Databind serialization/deserialization перетворює DTO у request body і response назад у object. null, missing field, empty object і empty array — різні contract states і потребують окремих tests.
40:00
Local IDE run проти Gradle/CI
В IntelliJ тести можуть запускатися IDE runner, а CI викликатиме Gradle/Maven command. Обидва шляхи мають компілювати та проходити з однаковими properties/environment variables.
Типовий failure: local run бачить IDE configuration, а CI не отримує required secret/property. Тому command-line run є окремою contract check, а не дублюванням IDE run.
50:00
Lombok, Builder і test data factories
Lombok @Data, constructors і @Builder зменшують boilerplate для generated/request models. Builder допомагає зібрати object з optional/nested fields без довгого constructor.
Створення valid default DTO можна винести в small factory/generator. Важливо не сховати за таким helper суттєві дані сценарію: у тесті має бути видно, що саме варіюється.
1:10:00
Resource controllers і negative responses
Коли один endpoint method потрібен кільком тесам, він переходить у resource controller/service. Межа class залежить від real API: окремий service на resource або кілька related resources в одном service client.
Для negative tests controller краще повертати raw Response, щоб test явно перевірив status, headers і error body. Примусова deserialization success DTO для 4xx/5xx сховає реальний contract.
Автор порівнює Controller, Service і API naming. Назва вторинна; головне, щоб class не змішував domains і не ховав assertions.
Не кожен endpoint потребує окремого class. Почати варто з одного resource client і розділяти, коли поточний class вже має кілька незалежних responsibilities.
Одна model для request і response придатна лише тоді, коли wire shapes справді збігаються. Якщо response має generated id/timestamps або request забороняє server-owned fields, потрібні separate PetRequest і PetResponse.
Невдала deserialization найчастіше означає incorrect DTO shape/type або Jackson configuration. Виправлення — звірити модель з real JSON/OpenAPI contract, а не додавати random annotations, доки exception не зникне.