Overview
Monei provides testing tools and utilities to help you develop and debug your integration. This guide covers available tools, debugging techniques, and testing strategies. What you’ll learn:- API testing tools
- Debugging techniques
- Mock data generators
- Automated testing
- CI/CD integration
API Testing Tools
Postman Collection
Import our Postman collection for quick API testing:1
Download Collection
Download the Monei Postman Collection
2
Import to Postman
Open Postman → Import → Select downloaded file
3
Configure Environment
Create environment with your API key:
{
"api_key": "sk_test_your_key_here",
"base_url": "https://api.dev.monei.cc"
}
4
Start Testing
Use pre-configured requests to test all endpoints
cURL Examples
Quick API testing from command line:# Get wallet information
curl https://api.dev.monei.cc/api/v1/wallet/me \
-H "x-api-key: sk_test_your_key_here"
# Initiate card deposit
curl -X POST https://api.dev.monei.cc/api/v1/wallet/deposit \
-H "x-api-key: sk_test_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"amount": 5000,
"method": "CARD",
"reference": "TEST-DEP-123",
"card": {
"cardNumber": "5531886652142950",
"cvv": "564",
"expiryMonth": "09",
"expiryYear": "32",
"cardHolderName": "TEST USER"
}
}'
# Get transaction history
curl "https://api.dev.monei.cc/api/v1/transactions/user?page=1&limit=10" \
-H "x-api-key: sk_test_your_key_here"
Mock Data Generators
Generate Test References
// Reference generator
function generateReference(prefix = 'TEST') {
const timestamp = Date.now();
const random = Math.random().toString(36).substring(2, 8).toUpperCase();
return `${prefix}-${timestamp}-${random}`;
}
// Usage
const depositRef = generateReference('DEP');
console.log(depositRef); // DEP-1708000000-A3X9K2
const payoutRef = generateReference('PAY');
console.log(payoutRef); // PAY-1708000000-B7Y4M1
const billRef = generateReference('BILL');
console.log(billRef); // BILL-1708000000-C5Z8N3
import time
import random
import string
def generate_reference(prefix='TEST'):
timestamp = int(time.time())
random_str = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6))
return f'{prefix}-{timestamp}-{random_str}'
# Usage
deposit_ref = generate_reference('DEP')
print(deposit_ref) # DEP-1708000000-A3X9K2
payout_ref = generate_reference('PAY')
print(payout_ref) # PAY-1708000000-B7Y4M1
Generate Test Data
// Test data generator
const testData = {
// Test phone numbers
generatePhone: () => {
const prefixes = ['0801', '0802', '0803', '0805', '0807', '0808'];
const prefix = prefixes[Math.floor(Math.random() * prefixes.length)];
const suffix = Math.floor(Math.random() * 10000000).toString().padStart(7, '0');
return prefix + suffix;
},
// Test meter numbers
generateMeter: () => {
return Math.floor(Math.random() * 100000000000).toString().padStart(11, '0');
},
// Test smartcard numbers
generateSmartcard: () => {
return Math.floor(Math.random() * 10000000000).toString().padStart(10, '0');
},
// Test amounts
generateAmount: (min = 100, max = 50000) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
// Test card
testCard: {
cardNumber: '5531886652142950',
cvv: '564',
expiryMonth: '09',
expiryYear: '32',
cardHolderName: 'TEST USER'
}
};
// Usage
console.log('Phone:', testData.generatePhone());
console.log('Meter:', testData.generateMeter());
console.log('Amount:', testData.generateAmount());
import random
class TestData:
@staticmethod
def generate_phone():
prefixes = ['0801', '0802', '0803', '0805', '0807', '0808']
prefix = random.choice(prefixes)
suffix = str(random.randint(0, 9999999)).zfill(7)
return prefix + suffix
@staticmethod
def generate_meter():
return str(random.randint(0, 99999999999)).zfill(11)
@staticmethod
def generate_smartcard():
return str(random.randint(0, 9999999999)).zfill(10)
@staticmethod
def generate_amount(min_amt=100, max_amt=50000):
return random.randint(min_amt, max_amt)
@staticmethod
def test_card():
return {
'card_number': '5531886652142950',
'cvv': '564',
'expiry_month': '09',
'expiry_year': '32',
'card_holder_name': 'TEST USER'
}
# Usage
print(f'Phone: {TestData.generate_phone()}')
print(f'Meter: {TestData.generate_meter()}')
print(f'Amount: {TestData.generate_amount()}')
Automated Testing
Unit Tests
// __tests__/wallet.test.js
const MoneiSDK = require('monei-sdk');
describe('Wallet Operations', () => {
let monei;
beforeAll(() => {
monei = new MoneiSDK({
apiKey: process.env.MONEI_SANDBOX_API_KEY,
environment: 'sandbox'
});
});
test('should get wallet information', async () => {
const wallet = await monei.wallet.me();
expect(wallet).toBeDefined();
expect(wallet.nairaBalance).toBeDefined();
expect(wallet.subwallets).toBeInstanceOf(Array);
});
test('should make deposit', async () => {
const deposit = await monei.wallet.depositWithCard({
amount: 5000,
reference: `TEST-${Date.now()}`,
card: {
cardNumber: '5531886652142950',
cvv: '564',
expiryMonth: '09',
expiryYear: '32',
cardHolderName: 'TEST USER'
}
});
expect(deposit.reference).toBeDefined();
expect(deposit.status).toBe('successful');
});
test('should handle insufficient balance', async () => {
const wallet = await monei.wallet.me();
const balance = parseFloat(wallet.nairaBalance);
await expect(
monei.payout.bankTransfer({
amount: balance + 10000, // More than balance
bank: '058',
accountNumber: '0123456789',
transactionPin: '1234'
})
).rejects.toThrow('Insufficient balance');
});
});
# tests/test_wallet.py
import pytest
from monei import MoneiClient
import os
@pytest.fixture
def monei():
return MoneiClient(
api_key=os.getenv('MONEI_SANDBOX_API_KEY'),
environment='sandbox'
)
def test_get_wallet(monei):
wallet = monei.wallet.me()
assert wallet is not None
assert hasattr(wallet, 'naira_balance')
assert isinstance(wallet.subwallets, list)
def test_make_deposit(monei):
deposit = monei.wallet.deposit_with_card(
amount=5000,
reference=f'TEST-{int(time.time())}',
card={
'card_number': '5531886652142950',
'cvv': '564',
'expiry_month': '09',
'expiry_year': '32',
'card_holder_name': 'TEST USER'
}
)
assert deposit.reference is not None
assert deposit.status == 'successful'
def test_insufficient_balance(monei):
wallet = monei.wallet.me()
balance = float(wallet.naira_balance)
with pytest.raises(Exception, match='Insufficient balance'):
monei.payout.bank_transfer(
amount=balance + 10000,
bank='058',
account_number='0123456789',
transaction_pin='1234'
)
Integration Tests
// __tests__/integration/bill-payment.test.js
describe('Bill Payment Flow', () => {
test('complete airtime purchase flow', async () => {
// 1. Get billers
const billers = await monei.bills.getBillers({ category: 'airtime' });
expect(billers.length).toBeGreaterThan(0);
const mtn = billers.find(b => b.shortName === 'MTN');
expect(mtn).toBeDefined();
// 2. Validate customer
const validation = await monei.bills.validate({
billerId: mtn.billerId,
customerId: '08012345678',
type: 'PREPAID'
});
expect(validation.validated).toBe(true);
expect(validation.customerName).toBeDefined();
// 3. Make payment
const payment = await monei.bills.pay({
billerId: mtn.billerId,
customerId: '08012345678',
amount: 100,
type: 'PREPAID'
});
expect(payment.status).toBe('successful');
expect(payment.reference).toBeDefined();
// 4. Verify transaction
const transaction = await monei.transactions.getByReference(payment.reference);
expect(transaction.status).toBe('SUCCESS');
});
});
# tests/integration/test_bill_payment.py
def test_complete_airtime_flow(monei):
# 1. Get billers
billers = monei.bills.get_billers(category='airtime')
assert len(billers) > 0
mtn = next(b for b in billers if b.short_name == 'MTN')
assert mtn is not None
# 2. Validate
validation = monei.bills.validate(
biller_id=mtn.biller_id,
customer_id='08012345678',
type='PREPAID'
)
assert validation.validated == True
assert validation.customer_name is not None
# 3. Pay
payment = monei.bills.pay(
biller_id=mtn.biller_id,
customer_id='08012345678',
amount=100,
type='PREPAID'
)
assert payment.status == 'successful'
assert payment.reference is not None
# 4. Verify
transaction = monei.transactions.get_by_reference(payment.reference)
assert transaction.status == 'SUCCESS'
CI/CD Integration
GitHub Actions
name: Test Monei Integration
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run tests
env:
MONEI_SANDBOX_API_KEY: ${{ secrets.MONEI_SANDBOX_API_KEY }}
run: npm test
- name: Upload coverage
uses: codecov/codecov-action@v3
GitLab CI
stages:
- test
test:
stage: test
image: node:18
variables:
MONEI_SANDBOX_API_KEY: $MONEI_SANDBOX_API_KEY
before_script:
- npm ci
script:
- npm test
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
Debugging Tools
Request/Response Logging
// Debug middleware
const debug = require('debug')('monei:api');
class MoneiDebugger {
constructor(sdk) {
this.sdk = sdk;
this.interceptRequests();
}
interceptRequests() {
const originalFetch = global.fetch;
global.fetch = async (...args) => {
const [url, options] = args;
// Log request
debug('REQUEST:', {
url,
method: options?.method || 'GET',
headers: options?.headers,
body: options?.body
});
const start = Date.now();
const response = await originalFetch(...args);
const duration = Date.now() - start;
// Log response
const responseData = await response.clone().json();
debug('RESPONSE:', {
status: response.status,
duration: `${duration}ms`,
data: responseData
});
return response;
};
}
}
// Usage
const monei = new MoneiSDK({ apiKey: process.env.MONEI_API_KEY });
new MoneiDebugger(monei);
// Enable debug logs
// DEBUG=monei:* node your-script.js
# Debug logger
import logging
import requests
import time
# Configure logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('monei.api')
class MoneiDebugger:
def __init__(self, client):
self.client = client
self.intercept_requests()
def intercept_requests(self):
original_request = requests.request
def debug_request(*args, **kwargs):
# Log request
logger.debug(f'REQUEST: {kwargs.get("method")} {kwargs.get("url")}')
logger.debug(f'Headers: {kwargs.get("headers")}')
logger.debug(f'Body: {kwargs.get("json")}')
start = time.time()
response = original_request(*args, **kwargs)
duration = (time.time() - start) * 1000
# Log response
logger.debug(f'RESPONSE: {response.status_code} ({duration:.0f}ms)')
logger.debug(f'Data: {response.json()}')
return response
requests.request = debug_request
# Usage
monei = MoneiClient(api_key=os.getenv('MONEI_API_KEY'))
MoneiDebugger(monei)
Error Tracking
const Sentry = require('@sentry/node');
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
});
// Wrap Monei calls
async function safeMoneiCall(fn, context) {
const transaction = Sentry.startTransaction({
op: 'monei.api',
name: context
});
try {
const result = await fn();
transaction.setStatus('ok');
return result;
} catch (error) {
transaction.setStatus('error');
Sentry.captureException(error, {
contexts: {
monei: { operation: context }
}
});
throw error;
} finally {
transaction.finish();
}
}
// Usage
const wallet = await safeMoneiCall(
() => monei.wallet.me(),
'wallet.me'
);
Performance Testing
Load Testing
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 10 }, // Ramp up
{ duration: '1m', target: 10 }, // Stay at 10
{ duration: '30s', target: 0 }, // Ramp down
],
};
export default function () {
const url = 'https://api.dev.monei.cc/api/v1/wallet/me';
const params = {
headers: {
'x-api-key': __ENV.MONEI_API_KEY,
},
};
const response = http.get(url, params);
check(response, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
// Run: k6 run --env MONEI_API_KEY=sk_test_... load-test.js
Best Practices
Test Early
Start testing during development, not after
Automate Tests
Create automated test suites for CI/CD
Use Mock Data
Generate realistic test data
Test Edge Cases
Test failures, timeouts, and errors
Monitor Tests
Track test coverage and results
Keep Tests Fast
Optimize test execution time
Next Steps
Sandbox
Learn about sandbox environment
Security
Security best practices
Error Handling
Handle errors properly
Webhooks
Test webhook integration

