March 19, 2021

Using stripe-mock with Laravel

Recently, while building Lemon Squeezy I came across the issue of mocking Stripe classes in a Laravel application. If you've ever built any kind of billing system using Stripe in Laravel and want to test it (which you should) you'll understand the problem. Stripe objects tend to be large and complex and not easy to replicate.

However, Stripe recently released stripe-mock which is described as:

a mock HTTP server that responds like the real Stripe API. It can be used instead of Stripe's testmode to make test suites integrating with Stripe faster and less brittle.

Sounds great! This way I don't have to mock Stripe classes in my Laravel tests but can instead just point my Stripe API requests to the mock server and it will return valid Stripe responses.

Using stripe-mock with Laravel turned out to be very simple. There are a bunch of different ways to run stripe-mock (e.g. go, homebrew etc.) but they also provide a docker image for the server. As I'm using Laravel Sail (docker) for my local dev environment, that means I can just plug stripe-mock into my docker-compose.yml:

stripemock:
  image: 'stripemock/stripe-mock:latest'
  networks:
    - sail

After a quick sail build, stripe-mock is now running along side my other containers. Now all I need to do is tell Laravel to point Stripe requests to this container instead of the real Stripe API during testing. This took a bit of digging into the Stripe PHP library to figure out but turned out to be relatively simple in the end. First, add a new api_base entry under your stripe config in config/services.php:

'stripe' => [
    'key'     => env('STRIPE_KEY'),
    'secret'  => env('STRIPE_SECRET'),
    'webhook' => [
        'secret' => env('STRIPE_WEBHOOK_SECRET'),
    ],
    'api_base' => env('STRIPE_API_BASE'), // <-- Add this
],

Next, in the boot method of your AppServiceProvider.php add the following:

public function boot()
{
    if ($stripeApiBase = config('services.stripe.api_base')) {
        \Stripe\Stripe::$apiBase = $stripeApiBase;
    }
}

This will tell the Stripe library to use our new config variable as the $apiBase for all Stripe requests. Finally, in your .env.testing or phpunit.xml set the new config variable to point to our stripe-mock container:

STRIPE_API_BASE="stripemock:12111"

Port 12111 is what stripe-mock uses for HTTP requests. That's it. Now your tests will run against the stripe-mock API instead of the real Stripe API.

Bonus: Using stripe-mock in GitHub Actions

As stripe-mock can be run as a docker container, it is also relatively simple to set up in CI environments. For example, to run stripe-mock in a GitHub Action you can simply add it as another service:

services:
  stripemock:
    image: stripemock/stripe-mock:latest
    ports:
      - 12111

Then when you run PHPUnit, set the API base as env variable:

- name: Run tests
  env:
    STRIPE_API_BASE: "127.0.0.1:${{ job.services.stripemock.ports[12111] }}"
  run: vendor/bin/phpunit

Looking for more?

Subscribe to my newsletter to get infrequent updates in your inbox. Or follow me on Twitter.