Тестування контрактів API: вправа з n8n перед імітацією запису
Практикуйте тестування контрактів API в n8n із синтетичними відповідями, явними перевірками полів та імітацією запису. Редакційна вправа з очікуваними результатами.

Перевірено за наведеними джерелами .
Ваше завдання й межі тестування контрактів API
Ця редакційна вправа використовує тестування контрактів API, щоб відповісти на вузьке запитання: чи містить контрольована відповідь поля, потрібні для запланованого запису? Створіть три вузли Code з назвами Mock response, Check contract і Simulated write. Ваше завдання — пропускати сумісні відповіді до маркера запису та зупиняти несумісні перед ним.
Передумови — робочий процес n8n для розробки, який можна редагувати, і базові знання JavaScript. Документація n8n описує створення тестових даних за допомогою вузлів Code або Edit Fields. Використовуйте лише синтетичні дані: без облікових даних, зовнішніх запитів до API чи реальних записів. У наданій документації не зазначено версію чи редакцію n8n, тому вона не підтверджує сумісність з усіма середовищами виконання або тарифними планами.
Наведені нижче тестові приклади, алгоритм і очікувані результати — це запропонований навчальний матеріал, а не виконаний чи перевірений робочий процес. Це написані вручну перевірки JavaScript, а не JSON Schema чи контракт, визначений споживачем і перевірений постачальником. Обробка статусів HTTP, інфраструктура регресійного тестування, відкат і розгортання у виробничому середовищі виходять за межі цієї вправи.
Sources: n8n-docs/docs/build/work-with-data/pin-and-mock-data.md at main · n8n-io/n8n-docs · GitHub
Підготуйте приклад тестування контрактів API

Використовуйте запропоновану для вправи оболонку з полями fixtureName і body. У Mock response повертайте один тестовий приклад за запуск як масив з об’єктом, властивість json якого містить цю оболонку. У структурі масиву елементів n8n значення json має бути об’єктом; сама правильна оболонка не підтверджує коректність вкладеної відповіді.
Запропонований контракт успішної відповіді вимагає, щоб body був об’єктом, відмінним від null і масиву, із власними властивостями id типу string та amount типу number. Дозволяйте сторонні додаткові поля й не перетворюйте типи значень. На нашу думку, корисний навчальний контракт має виражати потреби споживача, а не фіксувати кожне поле, яке випадково повертає постачальник.
Використайте ці запропоновані тестові приклади. Для кожного задайте назву його рядка як fixtureName; у таблиці наведено значення body та запропонований результат.
| Тестовий приклад | body | Очікуваний результат |
|---|---|---|
| baseline | {"id":"order-a","amount":12} | Маркер запису |
| extra-field | {"id":"order-a","amount":12,"note":"ok"} | Маркер запису |
| missing-id | {"amount":12} | Помилка контракту: id |
| string-amount | {"id":"order-a","amount":"12"} | Помилка контракту: amount |
| null-body | null | Помилка контракту: body |
| array-body | [] | Помилка контракту: body |
| upstream-error | {"error":{"code":"RATE_LIMITED","message":"Try later"}} | Помилка зовнішнього сервісу |
| missing-code | {"error":{"message":"Try later"}} | Помилка контракту: error.code |
| wrong-message | {"error":{"code":"RATE_LIMITED","message":12}} | Помилка контракту: error.message |
Sources: Common issues | Nodes | n8n Docs, Object.hasOwn() - JavaScript | MDN, typeof - JavaScript | MDN
Побудуйте перевірку контракту перед маркером

У Check contract виберіть режим Run Once for All Items і зчитайте const items = $input.all(). Документація n8n описує цей режим і спосіб доступу до вхідних даних. Реалізуйте наведений нижче запропонований алгоритм, перевіряючи кожен елемент, перш ніж щось повертати.
- Пройдіть циклом по items, зчитуючи json.fixtureName і json.body кожного елемента.
- Відхиліть body, якщо він дорівнює null, typeof body не дорівнює "object" або Array.isArray(body) повертає true.
- Якщо Object.hasOwn(body, "error"), вимагайте, щоб error був об’єктом, відмінним від null і масиву. Вимагайте, щоб його власні властивості code і message мали typeof "string".
- Для некоректних об’єктів помилки викидайте new Error з назвою тестового прикладу, текстом "Contract error" і полем, що не пройшло перевірку. Для правильної структури помилки викидайте "Upstream error" з назвою тестового прикладу та error.code.
- В інших випадках вимагайте Object.hasOwn(body, "id") і typeof body.id === "string"; вимагайте Object.hasOwn(body, "amount") і typeof body.amount === "number". Якщо будь-яка перевірка не пройшла, викидайте змістовну помилку контракту.
- Лише після завершення всього циклу повертайте items. Не повертайте прийняті елементи зсередини циклу.
Object.hasOwn() відрізняє власну властивість від відсутньої чи успадкованої; наявність властивості все одно потребує перевірки значення. Оператор JavaScript typeof визначає і null, і масиви як об’єкти, тому явно відсіюйте їх. Переконайтеся, що Object.hasOwn() доступний у вашому середовищі виконання.
Установіть для параметра On Error валідатора значення Stop Workflow: документація n8n зазначає, що воно запобігає подальшому виконанню вузлів після помилки. Натомість Continue продовжує виконання з останніми коректними даними. Зупинка не скасовує попередніх записів, тому в цій вправі маркер розташований після перевірки.
Sources: skills/skills/n8n-code-nodes-official/SKILL.md at main · n8n-io/skills · GitHub, Nodeinputdata, Object.hasOwn() - JavaScript | MDN, typeof - JavaScript | MDN, throw - JavaScript | MDN, Work with nodes, n8n-docs/docs/build/understand-workflows/workflow-components/work-with-nodes.md at main · n8n-io/n8n-docs · GitHub
Запускайте окремо й фіксуйте докази виконання

У Simulated write використайте $input.all().map(item => ({json: {wouldWrite: true, id: item.json.body.id}})) як значення, що повертається. Цей маркер — лише навчальний артефакт. Запускайте повну послідовність окремо для кожного тестового прикладу й записуйте отримане діагностичне повідомлення та те, чи виконався вузол маркера.
Використайте наведений нижче контрольний список як запропоновані критерії завершення тестування контрактів API. На нашу думку, вирішальне спостереження — чи доходить виконання до маркера після відхилення; самого зрозумілого повідомлення про помилку недостатньо.
Якщо маркер з’являється неочікувано, перевірте налаштування On Error валідатора й те, чи викидає він помилку до повернення даних. Якщо виникає помилка вихідних даних Code, перевірте оболонку масиву й те, чи є значення json об’єктом. Якщо null або масиви проходять перевірку, перегляньте захисні перевірки body, а не покладайтеся лише на typeof.
Sources: Nodeinputdata, typeof - JavaScript | MDN, throw - JavaScript | MDN, Work with nodes, n8n-docs/docs/build/understand-workflows/workflow-components/work-with-nodes.md at main · n8n-io/n8n-docs · GitHub, Common issues | Nodes | n8n Docs
Поміркуйте, що підтверджує проходження тестів із макетами
Для цієї вправи з тестування контрактів API запропоноване рішення — повна перевірка всіх вхідних даних, після якої йде окремий вузол маркера. Поміркуйте, чому додаткове поле дозволене, чому правильно сформована помилка зовнішнього сервісу все одно блокує маркер і які обов’язкові поля потрібні вашому реальному споживачеві.
Проходження цих тестів із макетами не доводить, що реальний постачальник досі відповідає контракту. У статті Contract Test 2011 року Martin Fowler розрізняє тестування з використанням двійника та перевірку того, чи відповідає йому зовнішній сервіс. Сприймайте записані результати як свідчення щодо цих тестових прикладів і цієї конфігурації робочого процесу.
Sources: Contract Test


