95 lines
2.9 KiB
Markdown
95 lines
2.9 KiB
Markdown
# Shunt Pattern
|
|
|
|
Shunts are fake connectors for testing. They mirror real API structures but return configurable mock data. No external service needed.
|
|
|
|
---
|
|
|
|
## Why Shunts
|
|
|
|
You need to test payment flows without charging real cards. You need to develop against an API that requires VPN access. You need predictable responses for BDD tests. Shunts solve all of these.
|
|
|
|
A shunt runs as a FastAPI app, same as a vein. Your code talks to it the same way it would talk to the real service. Swap the URL and you're testing against production.
|
|
|
|
## Structure
|
|
|
|
```
|
|
shunts/
|
|
└── {name}/
|
|
├── __init__.py
|
|
├── main.py # FastAPI app
|
|
├── run.py # Standalone runner
|
|
├── core/
|
|
│ └── config.py # Mock behavior settings
|
|
├── api/
|
|
│ └── routes.py # Mock endpoints
|
|
└── templates/ # Optional config UI
|
|
```
|
|
|
|
## Creating a Shunt
|
|
|
|
Start from the example template:
|
|
|
|
```bash
|
|
cp -r soleprint/artery/shunts/example soleprint/artery/shunts/yourservice
|
|
```
|
|
|
|
The example shunt provides:
|
|
|
|
- Health check endpoint
|
|
- Config UI at root path
|
|
- Catch-all GET/POST handlers that return responses from a `responses.json` file
|
|
- `SHUNT_DEPOT` environment variable for external response storage
|
|
|
|
Edit `responses.json` to define your fake responses:
|
|
|
|
```json
|
|
{
|
|
"GET /users": [{"id": 1, "name": "Test User"}],
|
|
"POST /orders": {"id": 999, "status": "created"}
|
|
}
|
|
```
|
|
|
|
For more complex behavior, replace the catch-all handlers with specific route implementations.
|
|
|
|
## MercadoPago Shunt
|
|
|
|
The MercadoPago shunt is a full mock of the MercadoPago payment API. It demonstrates what a production-grade shunt looks like.
|
|
|
|
**What it mocks:**
|
|
|
|
- Checkout Pro preferences (`POST /v1/preferences`)
|
|
- Payments (`POST /v1/payments`, `GET /v1/payments/{id}`)
|
|
- Merchant orders (`GET /v1/merchant_orders/{id}`)
|
|
- OAuth token exchange (`POST /oauth/token`)
|
|
- Webhook simulation (`POST /mock/webhook`)
|
|
|
|
**Testing controls:**
|
|
|
|
| Endpoint | Purpose |
|
|
|----------|---------|
|
|
| `POST /mock/config` | Set default payment status, error rate |
|
|
| `GET /mock/reset` | Clear all mock data |
|
|
| `GET /mock/stats` | Count of stored mock objects |
|
|
|
|
**Configurable behavior:**
|
|
|
|
- `default_payment_status` -- force all payments to approved, pending, or rejected
|
|
- `error_rate` -- probability (0-1) of random 500 errors
|
|
- `enable_random_delays` -- simulate real API latency
|
|
- `min_delay_ms` / `max_delay_ms` -- delay range in milliseconds
|
|
|
|
Data is generated using `datagen`'s MercadoPago generator. Stored in memory. Reset between test runs with `/mock/reset`.
|
|
|
|
## Running a Shunt
|
|
|
|
```bash
|
|
cd soleprint/artery/shunts/mercadopago
|
|
python run.py
|
|
```
|
|
|
|
Or configure it in your room's shunt registry so soleprint manages it.
|
|
|
|
## Room-Specific Shunts
|
|
|
|
Rooms can define their own shunts under `cfg/{room}/artery/shunts/`. These are merged into the build output alongside the core shunts.
|