Build a Paypal Sandbox for Load Testing in 10 Minutes

Tom Akehurst on

API Mocking, MockLab, Paypal, Performance Testing

Modern e-commerce websites and apps need to be fast and stable in order to avoid losing swathes of customers to competitors.

Achieving this requires regular performance testing of systems, but this is a problem for sites that accept payments with Paypal since running high load against their sandbox is specifically prohibited by their terms of service.

So what can you do?

One option is to simply have your load test stop short of the final step of your checkout. This is less than ideal for (hopefully) obvious reasons.

Another option is to mock the part of the app’s code that calls Paypal during load testing. This is an improvement, but still means critical bits of code used in production won’t be tested.

A better solution is to build a simulation of the Paypal API and connect your test environment to it.

MockLab is a tool specifically built for this purpose, and the rest of this article will focus on how you can use it to quickly construct a mock Paypal API suitable for performance testing.

Setup

To begin, you need to have logged into MockLab and created a new, empty mock API. You can sign up here if you haven’t already.

Once you’ve created a new mock API, grab a copy of its base URL. You can find this in the title bar:

Base URL

You’ll also need the client ID and client secret from your Paypal Sandbox account.

We’ve developed a simple demo app for this tutorial. If you’d like to download and run this you can find it at https://github.com/mocklab/mocklab-demo-app

Once you’ve checked out the app, set the Paypal endpoint in src/main/resources/application.properties to your mock API’s base URL:

App configuration

Then start the app:

[Linux/OSX]

export PAYPAL_CLIENT_ID=<your client ID>
export PAYPAL_CLIENT_SECRET=<your client secret>
 ./gradlew bootRun

[Windows]

set PAYPAL_CLIENT_ID=<your client ID>
set PAYPAL_CLIENT_SECRET=<your client secret>
gradlew bootRun

Recording initial stubs

In MockLab, hit the Record button, set the target URL as Paypal’s sandbox then start recording:

Stub recorder

Go to http://localhost:9000/paypal, enter an amount and complete a Payment:

Paypal demo app

Return to MockLab and stop recording. You should now see two stubs have been appeared in the list, one for the prepare payment step and one for execute payment.

If you wish you can test these with the internal request maker or an HTTP client like Postman:

Test request in Postman

Making performance ready

Recorded stubs are by default very specific. They will only be matched to an incoming request if the method, URL and body match exactly. In practice this means they’ll only work for the exact same payment ID and amount.

Additionally they will return the same response each time, meaning IDs and dates you’d expect to be unique between requests will be the same. This causes problems if, for instance, the payment ID is saved in a unique field by your app.

All of these issues can be resolved using MockLab’s advanced matching and templated responses.

Create payment

Open the create payment stub first (the one with URL /v1/payments/payment). The generated name is a bit ugly so you may wish to change this to something more readable.

Next up, in the Advanced section you’ll notice there’s a body matcher for the exact JSON that was sent during recording. We don’t need this, since we want to respond to any create payment request, so delete this.

Request body

We want to ensure we’re sending a unique payment ID in the response each time. To do this, we need to enable response templating:

Enable response templating

Then we need to generate a random ID for each response. We can do this by first assigning a variable by adding this line at the top of the response body:

{{#assign 'paymentId'}}PAY-{{randomValue length=24 type='ALPHANUMERIC' uppercase=true}}{{/assign}}

and replacing instances of the payment ID with the variable we set e.g.

"id": "{{paymentId}}"

We also may wish to set the create_time field to the current time, rather than it being fixed at the one captured at record time:

"create_time": "{{now}}"

Putting it all together it should look something like this:

Templated create payment body

Execute payment

We need to give similar treatment to the execute payment stub, with a key difference: rather than generating the payment ID at random, we want to extract it from the request URL.

You’ll notice the request URL for the execute step is also very specific - it will only match the exact payment ID passed. We can fix this by converting it to a regular expression (not that the URL match type has also changed to ‘Path Regex’):

URL regular expression

Next we’ll give the response body the same treatment as with the create payment stub, but extracting the ID from the URL:

{{#assign 'paymentId'}}{{request.path.[3]}}{{/assign}}

(Ensure you change substitute the paymentId variables now variables where appropriate as before)

Adding delays for extra realism

Since stubbed responses tend to return faster than from real APIs, this can create misleading outcomes when performance testing. To remedy this, you can add some artificial delay to your stubs:

Random delay

Validating your stubs

You may wish to quickly test your updated stubs before pressing them into service. Again, you can do this with a tool like Postman, or with MockLab’s own test request maker:

Test requester

Load testing

Now your mock API is ready for use. You can try it out by running the JMeter from the demo project and opening paypal-demo.jmx.

You can start JMeter like this:

[Linux/OSX]

cd mocklab-demo-app
apache-jmeter-4.0/bin/jmeter.sh

[Windows]

cd mocklab-demo-app
apache-jmeter-4.0/bin/jmeter

JMeter

Then just hit play to start testing!