Сесія про перевірку API після створення сутності та про ризики міграції даних: розподіл coverage між resource tests і business-flow tests, перевірку DTO/schema, втрату полів під час mapping, перенесення логіки з моноліту в мікросервіси та помилки routing через API gateway.
Примітка: конспект укладено за оригінальними українськими автоматичними субтитрами; назви архітектурних компонентів та інструментів нормалізовано за контекстом відео.
Після цього уроку ви зможете
Розділити detailed resource tests і ключові business-flow tests.
Перевіряти response schema, required fields, типи та значення, а не лише status code.
Виявляти mapping-регресії під час database або service migration.
Локалізувати gateway routing і header-forwarding failures.
Застосувати strict runtime validation для API payload.
Перевірка створеної сутності в event-driven системі
Питання учасника: якщо POST повернув 200 OK із порожнім body, чи достатньо цього для перевірки створення сутності. В event-driven архітектурі успішна відповідь може означати лише прийняття команди, а фактичний запис з’явиться пізніше, тому наступний GET перевіряє спостережуваний результат.
Лектор розділяє два типи coverage: сценарій для конкретного ресурсу та повний business flow. CRUD/resource test локалізує помилку в операціях над сутністю; сценарний тест перевіряє, що ланцюжок бізнес-дій працює цілісно. Один тип не замінює інший, бо дефект може проявитися лише на конкретному стику.
Що змінилося після запису
Що змінилося після запису
У відеоУ відео 200 OK використано як приклад response, після якого сутність у distributed system ще може потребувати окремої перевірки через GET.
АктуальноЗа RFC 9110 стандартним сигналом незавершеної асинхронної обробки є 202 Accepted; 200 OK означає, що request succeeded. Реальний тест має спиратися на контракт конкретного API й не виводити completion semantics лише зі status class.
Що змінилосяRFC 9110 published 2022-06
Термін
HTTP success semantics
RFC 9110 визначає 200 OK як успішне виконання request. Для POST content описує status або результат дії. 202 Accepted означає, що request прийнято, але обробку ще не завершено.
Практика
Матриця перевірок створення ресурсу
Для одного POST endpoint опишіть immediate response assertion і спосіб перевірки eventual result.
Додайте resource-schema assertions і один business-flow assertion.
Позначте, який тест локалізує кожен failure.
Результат: Таблиця з чотирма checks, test level і failure signal.
На спрощеній схемі є database table із полями користувача, entity для роботи з нею, service із бізнес-логікою та mapping, controller з endpoints і DTO, яке повертається клієнту. Response не обов’язково є прямою копією одного рядка: service може звертатися до іншої таблиці або зовнішньої системи, наприклад по taxId чи додаткові атрибути.
Поля на кшталт createdAt, updatedAt і deletedAt можуть зберігатися в базі, але не віддаватися назовні безпосередньо. DTO формує публічний контракт, а service відповідає за перетворення внутрішніх даних у цей контракт.
Навіть просте перейменування surname на lastName зачіпає кілька шарів: database/entity, зовнішній service, mapping і DTO. Якщо API має повертати fullName, service може формувати його з name та lastName; отже, механічне копіювання одного поля дасть синтаксично валідний, але семантично неправильний response.
Що більше полів і mapping rules, то вищий ризик пропустити зв’язок або зберегти не те значення. Тести мають перевіряти не лише наявність response, а й коректність значень після всіх перетворень.
Практика
Migration mapping checklist
Оберіть одну DTO з проєкту.
Для кожного field зафіксуйте source entity/service, mapping rule, nullability, required status, serializer behavior і regression test.
Додайте один gateway header, який має пройти до внутрішнього service.
Результат: Mapping table і один перевірений routing contract.
Під час декомпозиції логіку, яка раніше жила в одному або кількох класах, переносять у різні services. Треба не лише перенести записи, а й зберегти правила зіставлення полів та джерела кожного значення.
Показано типовий регресійний ланцюжок: fullName випадково мапиться лише з lastName; локальний fix додає name, але дані все одно не оновлюються, бо справжнім джерелом був інший service. Так само похідний status може формуватися з timestamps лише на одному code path і залишитися null під час читання.
Тест, який перевіряє тільки 200 OK, пропустить відсутнє поле, null, порожній рядок або неправильний mapping. Навіть перевірка переліку полів не гарантує правильного типу чи змісту.
Deserialization і schema validation дають дешевий базовий захист: response приводиться до строгої моделі, тому тест одразу виявляє відсутнє поле або неправильний тип. Для цього згадуються інструменти на кшталт Zod у TypeScript і Pydantic у Python. Окремо треба врахувати serializer settings: backend може зовсім вилучати з JSON поля зі значенням null.
Термін
OpenAPI Schema Object
OpenAPI 3.1 Schema Object описує структуру payload через JSON Schema vocabulary. Список required визначає обов’язкові properties; оголошення property саме по собі не робить його обов’язковим.
Термін
Pydantic strict mode
За замовчуванням Pydantic може перетворювати вхідні значення до потрібного типу. Strict mode зменшує coercion і повертає validation error, коли Python input має неправильний тип; правила для JSON input можуть відрізнятися для окремих типів.
Для критичних контрактів рекомендовано схилятися до strict validation: обов’язкове поле має бути присутнім і мати визначений тип. Щоб така перевірка була змістовною, test fixture треба створювати з повним набором даних, а не випадково залишати половину полів порожніми.
Генерація готових моделей прискорює роботу, але ручний red/green шлях іноді знаходить backend defects саме під час поступового заповнення й перевірки полів. Повністю «ідеальна» згенерована модель може приховати досвід негативних сценаріїв, хоча саме неочікувані дані часто відкривають проблеми.
Окремий resource test детально перевіряє schema, типи та mapping конкретної сутності. Business-flow test фокусується на ключових результатах і досяжності сценарію, не дублюючи кожну дрібну assertion з ресурсного рівня.
Частину детальних перевірок можна перенести на component/integration level, але лише якщо команда знає, що потрібний контракт там справді покритий і цим evidence можна довіряти. Інакше «це вже десь тестується» залишає реальну прогалину.
Клієнт звертається до одного зовнішнього API gateway, хоча за ним працюють окремі user/account та appointment services. Gateway перетворює зовнішній route і проксіює request у внутрішню мережу до відповідного service; зовнішнє й внутрішнє найменування ресурсу може відрізнятися.
Service, у свою чергу, може читати кілька tables, звертатися до інших services, виконувати filters і mappings, а controller повертає сформовану DTO. Тому response одного endpoint залежить не від одного методу, а від усього ланцюжка.
Під час міграції можна правильно перенести service, але помилитися в gateway route: не прокинути authorization header, body або інший обов’язковий параметр. Клієнт передасть credentials, gateway прийме request, а внутрішній service поверне 401, бо потрібний header загубився між ними.
API tests швидко виявляють такі дефекти mapping, schema й routing без довгого пошуку причини через UI. Практична стратегія сесії: окремо перевіряти контракт ресурсу, окремо — ключові business flows, а під час database чи infrastructure migration запускати обидва набори як regression coverage.