2.9 KiB
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:
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.jsonfile SHUNT_DEPOTenvironment variable for external response storage
Edit responses.json to define your fake responses:
{
"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 rejectederror_rate-- probability (0-1) of random 500 errorsenable_random_delays-- simulate real API latencymin_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
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.