McTaba Labs logo
Software EngineeringThe WhiteboardProjectsEventsMasterclassesWebinarsLearn
Book Call

500+ developers already in the community

Get answers, find accountability partners, and stay ahead

Join Discord →
McTaba Labs logo

Educating 1 million students in tech by 2030.

Programs

  • HighSchool Graduates Launchpad
  • AI & Business Automation
  • Corporate Training
  • McTaba Story & Mission
  • Full-Stack Curriculum
  • Course Pricing & Plans
  • Frequently Asked Questions

Resources

  • Join Discord Community
  • Tech Events in Nairobi
  • Masterclasses
  • Free Resources
  • Learn
  • Campus
  • Africa Tech Talent Report
  • Partner With Us
  • Start a Project
  • Our Work

Contact Us

  • 124 Manyani East Road, Lavington, Nairobi
  • +254727795603
  • Book a Discovery Call

Office Hours:

Mon-Fri: 9am - 2pm EAT

Sat: 10am - 12pm EAT

© 2027 McTaba Labs - A product of Edtech Industries. All rights reserved.

Privacy PolicyTerms of ServiceRefund Policy
  1. Learn
  2. Paystack for African Developers
  3. Seeding Test Data for a Payments Feature
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

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.

In this article

  1. 1. Test Data Seed Script
  2. 2. Using Seeded Data in Tests
  3. 3. Learn More

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 })
    );
  });
});

Get weekly developer tips

Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.

No spam. Unsubscribe anytime.

Learn More

This guide is part of the Paystack testing guide.

Sign up for the McTaba newsletter

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.

Learn Paystack Integration

KES 2,999

The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.

Start Paystack Course

Not ready? Create Free Account

Keep reading

Testing Paystack Integrations: The Complete Guide

A complete guide to testing Paystack integrations at every level: test mode, test cards, unit tests with mocks, integration tests, end-to-end flows with Playwright, webhook simulation, contract testing, CI pipelines, staging environments, load testing, and coverage targets for payment code.

Read more

Simulating Declined Cards on Paystack

A card decline is one of the most common failure states in a payment flow, and your application must handle it gracefully. This guide shows how to simulate specific card declines in Paystack test mode and how to verify your decline handling code works correctly.

Read more

Mocking the Paystack API in PHPUnit

PHPUnit tests for Paystack integrations in Laravel or PHP can run without any network calls using Laravel's Http::fake() or Mockery. This guide shows how to mock Paystack responses, test webhook handlers, and verify your payment logic in isolation.

Read more

Contract Testing Your Paystack Webhook Handler

Contract testing verifies that your webhook handler correctly handles the exact payload structure Paystack sends. If Paystack adds or renames a field, contract tests catch the mismatch before it reaches production. This guide shows how to write contract tests for Paystack webhook events.

Read more

Paystack Transaction Timed Out

A Paystack transaction timeout does not always mean the payment failed. Different channels time out at different points, and a webhook can still arrive minutes later. This guide covers every timeout scenario and the safe way to handle each one.

Read more

Explore related topics

M-Pesa & African Stack

M-Pesa Daraja API tutorials, USSD development, and WhatsApp Business API guides. The African Stack that global bootcamps do not teach.

Learn to Code in Kenya

Everything a Kenyan needs to know before writing their first line of code. Career paths, real costs, hardware requirements, and honest answers about what it takes.

Learning to Code

Roadmaps, language guides, and practical advice for learning to code and launching a programming career.

Breaking Into Tech

Practical, no-nonsense guides for anyone looking to start or change their career in tech. From choosing your first language to acing interviews.

The African Stack: Skills for This Market

The skills that make Kenyan developers hard to replace: M-Pesa, USSD, WhatsApp, fintech, and building for the African market.

Bonaventure Ogeto

Bonaventure Ogeto

Founder, McTaba Labs

Bonaventure is the founder of McTaba Labs, a coding bootcamp in Nairobi, Kenya. He has spent years building products for the African market and mentoring the next generation of developers across the continent.