Seeding Test Data for a Payments Feature
Seed Paystack test data in two places: (1) in Paystack test mode via API — create test plans, subaccounts, and customers using your sk_test key; (2) in your own database — insert matching orders, subscriptions, and payment records. Use a seed script that runs before your test suite and cleans up after. Reference the Paystack test objects by their codes (SUB_xxx, PLN_xxx) in your database seeds.
Test Data Seed Script
// scripts/seed-test-data.js
// Run before test suite: node scripts/seed-test-data.js
require('dotenv').config({ path: '.env.test' });
const db = require('./db');
async function paystackPost(endpoint, body) {
var res = await fetch('https://api.paystack.co' + endpoint, {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY, // sk_test_...
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
return res.json();
}
async function seed() {
// Create test subaccount
var subaccountRes = await paystackPost('/subaccount', {
business_name: 'Test Vendor',
settlement_bank: '057', // Zenith (test bank code)
account_number: '0000000001', // fake in test mode
percentage_charge: 80,
});
var subaccountCode = subaccountRes.data.subaccount_code;
// Create test plan for subscriptions
var planRes = await paystackPost('/plan', {
name: 'Test Monthly Plan',
interval: 'monthly',
amount: 500000, // NGN 5,000
});
var planCode = planRes.data.plan_code;
// Seed your database with matching records
await db.vendors.upsert({ id: 1, name: 'Test Vendor', subaccount_code: subaccountCode });
await db.plans.upsert({ id: 1, name: 'Monthly', paystack_plan_code: planCode, amount: 5000 });
await db.orders.upsert({ id: 1, email: 'test@example.com', amount: 10000, status: 'pending' });
// Save codes for use in tests
require('fs').writeFileSync('test-seeds.json', JSON.stringify({ subaccountCode, planCode }));
console.log('Test data seeded:', { subaccountCode, planCode });
process.exit(0);
}
seed().catch(e => { console.error(e); process.exit(1); });
Using Seeded Data in Tests
// tests/split-payment.test.js
const seeds = require('../test-seeds.json');
describe('Split payment checkout', () => {
it('creates transaction with correct subaccount code', async () => {
var paystack = require('../lib/paystack');
paystack.initializeTransaction = jest.fn().mockResolvedValue({
status: true,
data: { authorization_url: 'https://checkout.paystack.com/test', reference: 'ref_001' },
});
await checkoutWithSplit({
email: 'buyer@test.com',
amount: 10000,
vendor_id: 1, // Matches seeded vendor with known subaccount_code
});
expect(paystack.initializeTransaction).toHaveBeenCalledWith(
expect.objectContaining({ subaccount: seeds.subaccountCode })
);
});
});
Learn More
This guide is part of the Paystack testing guide.
Key Takeaways
- ✓Create Paystack test resources (plans, subaccounts) via API in a seed script before your test suite runs.
- ✓Store the codes (SUB_xxx, PLN_xxx) from the Paystack API response in your test database seeds.
- ✓Seed your database with orders, subscriptions, and payment records that reference the Paystack test codes.
- ✓Use a cleanup script to delete test data after the suite — or use test mode resources that don't need cleanup (they're isolated from live).
- ✓For webhook tests, construct realistic charge.success payloads that match the seeded order IDs and amounts.
- ✓Do not hardcode Paystack test codes across multiple test files — define them in one seed file and import them.
Frequently Asked Questions
- Do Paystack test mode subaccounts persist between test runs?
- Yes — objects created in Paystack test mode persist until deleted. Your seed script can check if a test subaccount already exists (by fetching list and filtering by business_name) and skip creation if it does. Or always recreate it — the old one remains but is unused.
- Should I use factory functions or static test data?
- Factory functions are better for tests that need many variations (e.g., orders with different amounts). Static seeded data is better for tests that reference specific Paystack codes (subaccount_code, plan_code) that must match what Paystack test mode has. Use both: static seed for Paystack objects, factory functions for your own database records.
- How do I handle test data cleanup when tests fail mid-run?
- Use database transactions that roll back on failure — most test frameworks support this. For Paystack objects created in test mode, they stay in test mode permanently (not on live) so leaving them is not a problem. Your own database records should be inside a transaction or truncated in a beforeEach hook.
- Can I use the same seed data for multiple test environments (local, CI)?
- Yes, but each environment needs its own Paystack test API key. Paystack test mode resources are account-scoped — a subaccount created with one test key is not visible to another. Use a shared test Paystack account for CI, or recreate resources in each environment's seed step.
Ready to build real-world apps?
Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.
Apply to the McTaba Marathon