Automated testing
Learn how to use automated testing in your Stripe integration.
Automated testing is a common part of application development, both for server and client-side code. Front-end interfaces, such as Stripe Checkout or the Payment Element, have security measures in place that prevent automated testing, and Stripe APIs are rate limited. However, you can simulate the output of our interfaces and API requests using mock data to test your application behaviour and its ability to handle errors.
Client side testing
If you want to test your application’s ability to recover from errors such as transaction declines when using the Payment Element, you can return a simulated error object by hard-coding error objects in your test code, or creating an API service that returns mock errors in an HTTP response. The error object represents what would be returned by the confirmPayment function when a card is declined. See the following section to learn how you can generate a simulated error object.
Generating an error object
First, use a Stripe UI element such as the Payment Element manually to produce an error object by confirming a test mode Payment Intent using one of the test card numbers for declined payments. Log the error during the confirmation process as shown below.
const { error } = await stripe.confirmPayment({ elements, confirmParams: { return_url: 'https://example.com' }, }) ; if (error) { console.log(error) }
This produces an error object logged to the browser console that resembles the one shown below. The specifics for properties such as error_
depend on the card used and the type of error it generates.
{ "charge": "{{CHARGE_ID}}", "code": "card_declined", "decline_code": "generic_decline", "doc_url": "https://docs.stripe.com/error-codes#card-declined", "message": "Your card has been declined.", "payment_intent": {"id": "{{PAYMENT_INTENT_ID}}", …}, "payment_method": {"id": "{{PAYMENT_METHOD_ID}}", …}, "request_log_url": "https://dashboard.stripe.com/test/logs/req_xxxxxxx", "type": "card_error" }
Modify your tests to return this error object instead of calling Stripe.js functions and the Stripe APIs. You can use different test cards to generate errors with different error codes to make sure your application properly handles each type of error.
Server side testing
You can use the same approach when testing server-side API calls. You can generate Stripe API responses manually for various errors and mock the response returned in backend automated testing.
For example, to write a test to validate that your application can correctly handle an off-session payment requiring 3DS, you can generate the response by creating a Payment Intent with the Payment Method pm_
and confirm set to true
.
This generates a Payment Intent with a status of requires_
, and other properties associated with 3DS Authentication like next_
.
{ "id": "{{PAYMENT_INTENT_ID}}", "object": "payment_intent", ... "next_action": { "type": "use_stripe_sdk", ... }, ... "status": "requires_confirmation", ... }
Generating PaymentIntent objects that reflect different stages of the Payment lifecycle allows you to test your application’s behaviour as the PaymentIntent transitions through various states. Use this approach in your automated testing to make sure your integration can successfully respond to different outcomes, such as requesting that the customer comes back on-session to authenticate a payment that requires a next action.
When to use this approach
The above examples all reference testing the behaviour of your application and are suitable to use in a continuous integration test suite. When you need to perform tests to validate the response of the Stripe API, making requests to the API in test mode is an acceptable approach. You can also use Stripe API requests to periodically validate that Stripe API responses haven’t changed – but you should perform these tests infrequently to avoid rate limits.