API Mocks
Staqr uses Microcks for sophisticated API mocking during integration testing. This guide covers how to use mock services in your development workflow.
Overview
API mocks allow you to:
- Develop without carrier access: Build integrations before credentials are available
- Test error scenarios: Simulate carrier errors, timeouts, and edge cases
- Validate contracts: Ensure your code sends valid requests per WSDL/OpenAPI specs
- Run CI/CD tests: Reliable integration tests without external dependencies
Quick Start
1. Start Mock Services
# Using Docker Compose (local development)
docker compose -f docker-compose.yml --profile mocks up -d
# Verify running
curl http://localhost:4750/api/health # Should return {"status":"UP"}
2. Import Carrier WSDL/OpenAPI
# Import Optus WSG WSDL
curl -X POST http://localhost:4750/api/artifact/upload \
-F "file=@mocks/microcks/import/optus-wsg-9.2.wsdl"
# Verify import
curl http://localhost:4750/api/services | jq '.[].name'
3. Configure Connection
# Use mock connection in development
export OPTUS_CONNECTION_ID=mock-optus-wsg
4. Run Integration Tests
pnpm test:integration
Mock Endpoints
When you import a WSDL or OpenAPI spec, Microcks creates mock endpoints:
| Protocol | Endpoint Pattern | Example |
|---|---|---|
| SOAP | /soap/{ServiceName}/{Version} | /soap/WsgServiceOrderService/9.2 |
| REST | /rest/{APIName}/{Version}/{path} | /rest/TelstraAPI/1.0/customers/{id} |
Writing Integration Tests
Basic Integration Test
// packages/server/api/src/test/optus-adapter.integration.test.ts
import { describe, it, expect, beforeAll } from 'vitest'
import { optusWsgAdapter } from '../app/carrier/adapters/optus-wsg-adapter'
describe('Optus WSG Adapter', () => {
beforeAll(async () => {
// Ensure Microcks is ready
const health = await fetch('http://localhost:4750/api/health')
expect(health.ok).toBe(true)
})
it('should submit service order', async () => {
const adapter = await optusWsgAdapter('mock-optus-wsg')
const result = await adapter.submitServiceOrder({
orderType: 'NEW',
msisdn: '0412345678',
serviceId: 'SVC-001'
})
expect(result.orderId).toBeDefined()
expect(result.status).toBe('SUBMITTED')
})
})
Testing Error Scenarios
Configure Microcks to return different responses based on headers:
it('should handle throttle error', async () => {
const adapter = await optusWsgAdapter('mock-optus-wsg')
const result = await adapter.submitServiceOrder(
{ orderType: 'NEW', msisdn: '0412345678' },
{ headers: { 'X-Test-Scenario': 'throttle' } }
)
expect(result.error).toBe('RATE_LIMIT_EXCEEDED')
expect(result.retryAfter).toBeDefined()
})
CI/CD Integration
GitLab CI Configuration
Mock services run as service containers in GitLab CI:
integration-tests:
stage: test
image: node:20-alpine
services:
- name: quay.io/microcks/microcks:1.9.0
alias: microcks
variables:
SPRING_PROFILES_ACTIVE: uber
KEYCLOAK_ENABLED: "false"
variables:
MICROCKS_URL: http://microcks:8080
OPTUS_CONNECTION_ID: mock-optus-wsg
before_script:
- apk add --no-cache curl
- pnpm install --frozen-lockfile
# Wait for Microcks
- |
for i in $(seq 1 30); do
curl -s ${MICROCKS_URL}/api/health | grep -q "UP" && break
sleep 2
done
# Import mocks
- |
curl -X POST ${MICROCKS_URL}/api/artifact/upload \
-F "file=@mocks/microcks/import/optus-wsg-9.2.wsdl"
script:
- pnpm test:integration
Jest/Vitest Configuration
// vitest.integration.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
include: ['**/*.integration.test.ts'],
globalSetup: './src/test/setup-microcks.ts',
testTimeout: 30000,
}
})
// src/test/setup-microcks.ts
export async function setup() {
const MICROCKS_URL = process.env.MICROCKS_URL || 'http://localhost:4750'
// Wait for Microcks
for (let i = 0; i < 30; i++) {
try {
const res = await fetch(`${MICROCKS_URL}/api/health`)
if (res.ok) break
} catch (e) {
await new Promise(r => setTimeout(r, 2000))
}
}
// Import mock definitions
const mockFiles = ['mocks/microcks/import/optus-wsg-9.2.wsdl']
for (const file of mockFiles) {
const formData = new FormData()
formData.append('file', await Bun.file(file))
await fetch(`${MICROCKS_URL}/api/artifact/upload`, {
method: 'POST',
body: formData
})
}
}
Contract Testing
Microcks can validate that your adapter sends correct requests:
# Run contract test against your adapter
curl -X POST http://localhost:4750/api/tests \
-H "Content-Type: application/json" \
-d '{
"serviceId": "WsgServiceOrderService:9.2",
"testEndpoint": "http://host.docker.internal:4600/api/v1/carrier/optus-wsg",
"runnerType": "SOAP_HTTP"
}'
Response indicates PASS/FAIL with validation details:
{
"success": true,
"testNumber": 1,
"testCaseResults": [
{
"operationName": "SubmitServiceOrder",
"success": true
}
]
}
Directory Structure
mocks/
├── microcks/
│ └── import/
│ ├── optus-wsg-9.2.wsdl # Optus WSG SOAP contract
│ └── telstra-api-1.0.yaml # Telstra REST contract
└── mockoon/
└── carrier-mocks.json # Simple REST mocks
Best Practices
1. Version Mock Definitions
git add mocks/microcks/import/
git commit -m "feat: add Optus WSG v9.2 mock definition"
2. Use Realistic Data
{
"msisdn": "0412345678", // Valid AU mobile
"abn": "51824753556", // Valid ABN
"postcode": "2000" // Valid postcode
}
3. Document Scenarios
# mocks/README.md
## Optus WSG Mock Scenarios
| Header | Response |
|--------|----------|
| X-Test-Scenario: throttle | 503 Rate Limited |
| X-Test-Scenario: timeout | 30s delay |
| X-Test-Scenario: invalid-msisdn | 400 Validation Error |
4. Same Mocks in CI
Ensure CI uses the same mock definitions as local development:
before_script:
- curl -X POST ${MICROCKS_URL}/api/artifact/upload \
-F "file=@mocks/microcks/import/optus-wsg-9.2.wsdl"
Troubleshooting
See Mock Services Operations Guide for troubleshooting common issues.