# Testes de Contrato: Consumer-Driven Contracts

**Meta Description:** Aprenda testes de contrato: Pact, contratos entre microservices, consumer-driven testing e como evitar breaking changes.

---

## O Que São Testes de Contrato?

Testes de contrato verificam que a interface entre serviços (API) está funcionando conforme acordado. Cada serviço define o que espera e o que fornece.

### Problema

```
Microservice A (Consumer)
        ↓
    API REST
        ↓
Microservice B (Provider)

Se B muda API sem avisar A → BUG!
```

### Solução: Contract Testing

```
┌─────────────┐                    ┌─────────────┐
│  Consumer   │    Contract       │  Provider   │
│   Test      │ ←──────────────→ │   Test      │
└─────────────┘                    └─────────────┘
     ↓                                  ↓
[Pact Broker] ←──────────────────────────
```

---

## Pact - Framework de Contract Testing

### Setup

```bash
# Ruby
gem install pact

# Python
pip install pact-python

# Java
<dependency>
    <groupId>au.com.dius.pact</groupId>
    <artifactId>jvm-consumer</artifactId>
    <version>4.6.4</version>
</dependency>
```

### Consumer Test (Python)

```python
# test_consumer.py
import pact

# Provider URL
PACT_MOCK_PROVIDER_URL = "http://localhost:1234"

# Define consumer and provider
consumer = pact.Consumer('OrderService')
provider = pact.Provider('ProductService')

# Create pact
order_service_pact = consumer.has_pact_with(
    provider,
    pact_dir='./pacts',
    log_dir='./logs'
)

# Test
order_service_pact.given(
    'product with id 1 exists'
).upon_receiving(
    'a request for product details'
).with_request(
    method='GET',
    path='/products/1'
).will_respond_with(
    status=200,
    headers={'Content-Type': 'application/json'},
    body={
        'id': 1,
        'name': pact.Match.something_like('Test Product'),
        'price': pact.Match.decimal(99.99),
        'in_stock': pact.Match.boolean(True)
    }
)

# Verify
with order_service_pact:
    result = requests.get(f'{PACT_MOCK_PROVIDER_URL}/products/1')
    assert result.status_code == 200
    assert result.json()['name'] == 'Test Product'
```

### Provider Test (Python)

```python
# test_provider.py
import pact
from pact import Verifier

# Verify against provider
verifier = Verifier(
    provider='ProductService',
    provider_base_url='http://localhost:8000'
)

# Set up Pact file to verify
verifier.provider_states(
    'http://localhost:8000',
    set_up=lambda state: create_test_product() if state == 'product with id 1 exists' else None,
    tear_down=lambda state: delete_test_product() if state == 'product with id 1 exists' else None
)

# Verify contracts
result = verifier.verify_pacts(
    './pacts/order_service-product_service.json',
    verbose=True
)

assert result == 0, f"Pact verification failed: {result}"
```

---

## Pact Broker

```bash
# Publish contract
pact-broker publish ./pacts \
  --consumer-app-version=1.0.0 \
  --broker-base-url=https://pact-broker.example.com \
  --broker-token=YOUR_TOKEN

# Can I Deploy?
pact-broker can-i-deploy \
  --pacticipant=OrderService \
  --version=1.0.0 \
  --to-environment=production
```

---

## Conclusão

Contract testing previne breaking changes. As chaves são:

1. **Consumer-driven** - Cada cliente define necessidades
2. **Pact broker** - Centraliza contratos
3. **Verificação contínua** - CI valida mudanças
4. **Can I Deploy** - Bloca deploys incompatíveis
