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. Mocking the Paystack API in PHPUnit
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Mocking the Paystack API in PHPUnit

In Laravel: use Http::fake() to intercept Paystack API calls before they hit the network. Return fake responses for the initialize and verify endpoints. In plain PHP: inject a Paystack client interface and use Mockery::mock() in tests. For webhook testing, generate a valid HMAC signature in your test and POST directly to your webhook controller.

In this article

  1. 1. Laravel Http::fake() for Paystack
  2. 2. Plain PHP with Mockery
  3. 3. Learn More

Laravel Http::fake() for Paystack

// tests/Feature/PaymentTest.php
use IlluminateSupportFacadesHttp;
use TestsTestCase;

class PaymentTest extends TestCase
{
    public function test_checkout_returns_authorization_url(): void
    {
        Http::fake([
            'https://api.paystack.co/transaction/initialize' => Http::response([
                'status' => true,
                'data' => [
                    'authorization_url' => 'https://checkout.paystack.com/test',
                    'access_code' => 'test_access',
                    'reference' => 'ref_test_001',
                ],
            ], 200),
        ]);

        $response = $this->postJson('/api/checkout', [
            'email' => 'user@test.com',
            'amount' => 10000,
            'order_id' => 1,
        ]);

        $response->assertStatus(200)
                 ->assertJson(['authorization_url' => 'https://checkout.paystack.com/test']);
    }

    public function test_webhook_processes_charge_success(): void
    {
        $order = Order::factory()->create(['status' => 'pending']);
        $secret = config('services.paystack.secret_key');

        $payload = json_encode([
            'event' => 'charge.success',
            'data' => [
                'reference' => 'ref_test_001',
                'amount' => 1000000,
                'status' => 'success',
                'metadata' => ['order_id' => $order->id],
            ],
        ]);

        $signature = hash_hmac('sha512', $payload, $secret);

        $response = $this->withHeaders([
            'x-paystack-signature' => $signature,
        ])->postJson('/webhook/paystack', json_decode($payload, true));

        $response->assertStatus(200);
        $this->assertDatabaseHas('orders', [
            'id' => $order->id,
            'status' => 'paid',
        ]);
    }
}

Plain PHP with Mockery

// Plain PHP test with Mockery
use PHPUnitFrameworkTestCase;
use Mockery;

class PaymentServiceTest extends TestCase
{
    public function test_returns_checkout_url_on_success(): void
    {
        $paystackMock = Mockery::mock(PaystackClient::class);
        $paystackMock->shouldReceive('initializeTransaction')
                     ->once()
                     ->with(Mockery::on(fn($args) => $args['email'] === 'user@test.com'))
                     ->andReturn([
                         'status' => true,
                         'data' => ['authorization_url' => 'https://checkout.paystack.com/test'],
                     ]);

        $service = new PaymentService($paystackMock);
        $result = $service->createCheckout('user@test.com', 10000);

        $this->assertEquals('https://checkout.paystack.com/test', $result['url']);
    }

    protected function tearDown(): void
    {
        Mockery::close();
    }
}

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

  • ✓In Laravel, use Http::fake() to intercept Paystack API calls — no real HTTP request is made.
  • ✓Match the fake response structure to what Paystack actually returns: { status: true, data: { reference, amount, status } }.
  • ✓For webhook tests, generate the HMAC SHA512 signature in the test: hash_hmac("sha512", $body, $secret).
  • ✓Use Mockery::mock() or PHPUnit createMock() if you have a Paystack service class — mock the interface, not the HTTP client.
  • ✓Test the decline scenario by returning { status: false, data: { gateway_response: "Do Not Honor" } } from your Http fake.
  • ✓In Laravel, use RefreshDatabase trait so each test starts with a clean database state.

Frequently Asked Questions

Does Http::fake() intercept all Paystack API calls in Laravel?
Http::fake() intercepts calls made through Laravel's HTTP client (Http:: facade or the underlying Guzzle client that Laravel wraps). If your Paystack integration uses curl directly or a third-party SDK that does not use Laravel's HTTP client, Http::fake() will not intercept it — use Mockery instead.
How do I test the Paystack webhook signature validation in PHPUnit?
Generate a valid HMAC SHA512 signature in your test using the same algorithm your handler uses: $signature = hash_hmac("sha512", $rawBody, $secret). Set this as the x-paystack-signature header in your test POST request. To test invalid signature rejection, change one character of the signature and assert the handler returns 401.
What PHPUnit version is required for these patterns?
PHPUnit 10+ (the current standard with Laravel 11+). The patterns shown work with PHPUnit 9 and 10. Http::fake() requires Laravel 7+ — it was introduced with Laravel's built-in HTTP client.
Should I use Http::fake() or a Paystack SDK mock?
If you call the Paystack API directly via Laravel's Http client, use Http::fake(). If you use a Paystack PHP SDK (like unicodeveloper/paystack or yabacon/paystack-php), mock the SDK class with Mockery — it has its own HTTP layer that Http::fake() may not intercept.

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

Integration Testing Paystack Flows End to End

Integration tests for Paystack test the real flow — your backend calls the actual Paystack test API, a webhook fires to your server, and your database is updated. Unlike unit tests with mocks, integration tests catch issues that only appear when the real API is involved.

Read more

Seeding Test Data for a Payments Feature

Good test data is essential for testing payment features. This guide covers creating Paystack test mode resources (plans, subaccounts, split codes) and seeding your application database with matching payment records for realistic test scenarios.

Read more

Paystack Amount Too Low Error

Paystack rejects transactions below a minimum amount that varies by currency. This guide lists every minimum, explains the kobo/pesewa/cents confusion that causes most "amount too low" errors, and gives you a server-side validation function to catch the problem before it reaches the API.

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.