Middle+
Parla dei test di contratto di un microservizio.
sobes.tech AI
Risposta dell'AI
I test di contratto si concentrano sulla verifica dell'interazione tra microservizi a livello di API (contratto). L'obiettivo è assicurarsi che il consumatore (servizio che utilizza l'API) e il fornitore (servizio che fornisce l'API) rispettino un "contratto" definito (schema delle richieste/risposte, formato dei dati, aspettative).
Principi fondamentali:
- Orientato al consumatore: I test si basano sulle aspettative del consumatore. Il consumatore determina quali dati e formati sono necessari.
- Test bidirezionali: Si verifica sia la capacità del consumatore (di lavorare con il contratto attuale) sia quella del fornitore (di rispettare le aspettative del consumatore).
- Velocità: I test vengono eseguiti rapidamente, spesso in una pipeline CI/CD, poiché non richiedono il deployment di tutti i servizi dipendenti.
Il processo generalmente include:
- Il consumatore crea test che descrivono le sue aspettative sull'API del fornitore. Questi test generano un "contratto".
- Il contratto viene pubblicato (ad esempio, in un repository centralizzato).
- Il fornitore utilizza il contratto pubblicato per verificare la propria implementazione dell'API. Esegue i test (solitamente lato fornitore), che verificano se la sua API è conforme al contratto.
- In caso di discrepanze tra le aspettative del consumatore e l'implementazione del fornitore, il test fallisce, indicando una violazione del contratto.
Strumenti:
- Pact (il più popolare)
- Spring Cloud Contract
- Swagger/OpenAPI con strumenti di validazione
Vantaggi:
- Rilevamento precoce degli errori di integrazione: I problemi di compatibilità vengono rilevati prima del deployment.
- Riduzione della necessità di test di integrazione: Diminuisce la dipendenza da test end-to-end complessi e lenti.
- Test indipendenti: Permette di testare i servizi in modo indipendente.
- Definizione chiara delle aspettative: Definisce esplicitamente il contratto tra i servizi.
Svantaggi:
- Non sostituisce completamente i test di integrazione (verifica solo l'interazione a livello di API).
- Richiede disciplina nella gestione delle versioni dei contratti.
- Può essere più complesso per servizi con contratti molto complessi.
Esempio di utilizzo con Pact:
- Il consumatore (ad esempio, il servizio
Order Service) utilizza la libreria Pact per creare test del lato consumatore.// Esempio di test del consumatore con 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 { // Logica chiamata API fornitore tramite mockServer // Verifica che il consumatore gestisca correttamente la risposta mockata HttpResponse response = Request.Get(mockServer.getUrl() + "/products/1").execute().returnResponse(); assertThat(response.getStatusLine().getStatusCode(), equalTo(200)); } } - Durante l'esecuzione dei test del lato consumatore, viene generato un file di contratto (
.json). - Questo file di contratto viene pubblicato in un Pact Broker o in un altro repository centralizzato.
- Il fornitore (
Product Service) utilizza la libreria Pact (ad esempio, Pact Provider Verifier) per verificare la propria implementazione API basata sul contratto ottenuto da Pact Broker.// Esempio di test del fornitore con Pact Provider Verifier @Provider("ProductService") @PactFolder("relative/path/to/pacts") // o usare 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() { // Logica di preparazione dello stato dei dati nel servizio fornitore per il test } // Aggiungi l'URL del provider dove il servizio in test è in esecuzione @BeforeEach void beforeEach(PactVerificationContext context) { context.setTarget(new HttpTestTarget("localhost", 8080)); } } - Il verificatore lato fornitore chiama l'API reale del fornitore secondo la specifica del contratto e confronta la risposta ottenuta con quella attesa nel contratto.
Il test di contratto è una pratica importante per garantire l'affidabilità e la manutenibilità dei sistemi basati su microservizi.