Middle+
дар бораи санҷиши шартномаи микросервис гӯед.
sobes.tech AI
Ҷавоб аз AI
Тестування на основі контракту зосереджено на перевірці взаємодії між мікросервісами на рівні їх API (контракт). Мета — переконатися, що споживач (сервіс, який використовує API) і постачальник (сервіс, який надає API) дотримуються певного "контракту" (схеми запитів/відповідей, формату даних, очікувань).
Основні принципи:
- Споживач-орієнтований: Тести базуються на очікуваннях споживача. Споживач визначає, які дані і формати йому потрібні.
- Двостороннє тестування: Перевіряється, чи може сторона споживача працювати з поточним контрактом, і чи відповідає реалізація сторони постачальника очікуванням споживача.
- Швидкість: Тести виконуються швидко, часто у рамках CI/CD, оскільки не вимагають розгортання всіх залежних сервісів.
Процес зазвичай включає:
- Споживач створює тести, що описують його очікування від API постачальника. Ці тести генерують "контракт".
- Контракт публікується (наприклад, у централізованому репозиторії).
- Постачальник використовує опублікований контракт для верифікації своєї реалізації API. Він запускає тести (зазвичай на стороні постачальника), які перевіряють, чи відповідає його API контракту.
- У разі розбіжностей між очікуваннями споживача і реалізацією постачальника, тест падає, вказуючи на порушення контракту.
Інструменти:
- Pact (найпопулярніший)
- Spring Cloud Contract
- Swagger/OpenAPI з інструментами валідації
Переваги:
- Раннє виявлення помилок інтеграції: Проблеми сумісності виявляються ще до розгортання.
- Зменшення необхідності інтеграційних тестів: Знижує залежність від складних і повільних сквозних тестів.
- Незалежне тестування: Дозволяє тестувати сервіси незалежно один від одного.
- Чітке визначення очікувань: Явно визначає контракт між сервісами.
Недоліки:
- Не замінює повністю інтеграційні тести (тільки перевіряє взаємодію на рівні API).
- Вимагає дисципліни у версіонуванні контрактів.
- Може бути складніше для сервісів з дуже складними контрактами.
Приклад використання з Pact:
- Споживач (наприклад, сервіс
Order Service) використовує бібліотеку Pact для створення тестів з боку споживача.// Приклад тесту споживача з Pact JVM @ExtendWith(PactConsumerTestExt.class) @PactTestFor(providerName = "ProductService", port = "8080") public class ProductServiceContractTest { @Pact(consumer = "OrderService") public RequestResponsePact createPact(PactDslWithRequest r) { return r.given("a product with id 1 exists") .uponReceiving("a request for product by id") .path("/products/1") .method("GET") .willRespondWith() .status(200) .headers(Map.of("Content-Type", "application/json")) .body(new PactDslJsonBody() .stringValue("id", "1") .stringValue("name", "Laptop") .numberType("price", 1200.00)) .toPact(); } @Test void testGetProductById(MockServer mockServer) throws IOException { // Логіка виклику API постачальника через mockServer // Перевірка, що споживач правильно обробля мок-відповідь HttpResponse response = Request.Get(mockServer.getUrl() + "/products/1").execute().returnResponse(); assertThat(response.getStatusLine().getStatusCode(), equalTo(200)); } } - При виконанні тестів споживача генерується файл контракту (
.json). - Цей файл публікується у Pact Broker або інше централізоване сховище.
- Постачальник (
Product Service) використовує бібліотеку Pact (наприклад, Pact Provider Verifier) для верифікації своєї реалізації API на основі контракту, отриманого з Pact Broker.// Приклад тесту постачальника з Pact Provider Verifier @Provider("ProductService") @PactFolder("relative/path/to/pacts") // або використання Pact Broker public class ProductServiceVerificationTest { @TestTemplate @ExtendWith(PactVerificationInvocationContextProvider.class) public void verifyPact(PactVerificationContext context) { context.verifyInteraction(); } @State("a product with id 1 exists") public void productWithId1Exists() { // Логіка підготовки стану даних у сервісі постачальника для тесту } // Додаємо URL постачальника, де запущена тестована служба @BeforeEach void beforeEach(PactVerificationContext context) { context.setTarget(new HttpTestTarget("localhost", 8080)); } } - Верифікатор зі сторони постачальника викликає реальний API постачальника згідно з специфікацією контракту і порівнює отриману відповідь з очікуваною у контракті.
Контрактне тестування є важливою практикою для забезпечення надійності та підтримуваності систем на базі мікросервісів.