Testing Stripe — Test Cards and Payment Scenarios
In this tutorial, you will learn about Testing Stripe. We cover key concepts, practical examples, and best practices to help you master this topic.
Stripe test mode provides fake card numbers that simulate different payment scenarios including success, decline, 3D Secure authentication, and insufficient funds.
What You'll Learn
By the end of this lesson you will understand how to use Stripe test cards, simulate various payment scenarios, test 3D Secure, handle declines, and validate your integration.
Why It Matters
Thorough testing prevents production issues like failed payments, incorrect subscription handling, or security vulnerabilities. Stripe's test cards let you simulate every payment scenario without real money.
Real-World Use
DodaZIP's QA team tests all payment flows with Stripe test cards before each deployment: success with 4242, 3D Secure with 4000002500003155, and declines with 4000000000000002.
flowchart LR
T[Test Cards] --> S[4242 - Success]
T --> D[4000...0002 - Decline]
T --> TDS[4000...3155 - 3DS]
T --> I[4000...0119 - Insufficient]
T --> P[4000...9989 - Processing Error]
style T fill:#6772e5,color:#fff
Common Test Cards
| Card Number | Scenario |
|---|---|
| 4242 4242 4242 4242 | Success (no authentication) |
| 4000 0025 0000 3155 | Requires 3D Secure |
| 4000 0000 0000 0002 | Card declined |
| 4000 0000 0000 0119 | Insufficient funds |
| 4000 0000 0000 9989 | Processing error |
| 4000 0000 0000 3220 | CVC check failed |
| Any date in the future | Valid expiration |
| Any 3-digit CVC | Valid CVC |
# test_cards.py
# Using test cards
def test_payment_scenario(card_number, expected_outcome):
print(f"Testing card: {card_number[:4]}...{card_number[-4:]}")
print(f" Expected: {expected_outcome}")
scenarios = {
"4242": {"status": "succeeded", "message": "Payment successful"},
"0002": {"status": "declined", "message": "Card declined - try another card"},
"3155": {"status": "requires_action", "message": "3D Secure required - authenticate"},
"0119": {"status": "declined", "message": "Insufficient funds"},
"9989": {"status": "failed", "message": "Processing error"},
}
prefix = card_number[-8:-4] if len(card_number) >= 8 else "0000"
scenario = scenarios.get(prefix, {"status": "succeeded", "message": "Payment successful"})
print(f" Actual: {scenario['status']} - {scenario['message']}")
passed = scenario['status'] == expected_outcome or expected_outcome == "any"
print(f" {'PASS' if passed else 'FAIL'}\n")
return passed
test_payment_scenario("4242424242424242", "succeeded")
test_payment_scenario("4000000000000002", "declined")
test_payment_scenario("4000002500003155", "requires_action")
Expected output:
Testing card: 4242...4242
Expected: succeeded
Actual: succeeded - Payment successful
PASS
...
Testing 3D Secure
Use the 3D Secure test card to validate your authentication flow.
# test_3ds.py
# Testing 3D Secure flow
def simulate_3ds_flow(card_number):
print("--- 3D Secure Test Flow ---")
print(f"1. Create PaymentIntent with card {card_number[-4:]}")
print("2. PaymentIntent status: requires_action")
print("3. Authentication required by bank")
print("4. Complete authentication in test modal:")
print(" - Click 'Complete authentication' to succeed")
print(" - Click 'Fail authentication' to fail")
print("5. After authentication, status: succeeded")
print("\nTest card: 4000002500003155")
print("Any CVC, any future date")
print("\nAuthentication decisions:")
print(" 'Y' (Complete) -> Payment succeeds")
print(" 'N' (Fail) -> Payment fails with authentication failure")
simulate_3ds_flow("4000002500003155")
Testing Webhooks
Use the Stripe CLI to trigger test Webhook events.
# Trigger test events
stripe trigger payment_intent.succeeded
stripe trigger checkout.session.completed
stripe trigger customer.subscription.updated
# Forward webhooks to local server
stripe listen --forward-to localhost:3000/api/webhooks
Common Mistakes
Testing only the success path: Test declines, 3D Secure, expired cards, and insufficient funds to ensure your error handling works.
Using test cards in production: Test cards succeed in test mode but fail in live mode. Always verify you are in test mode.
Not testing webhook scenarios: Trigger webhook events with the Stripe CLI to verify your webhook handler works correctly.
Forgetting to test idempotency: Send the same request twice to ensure your system handles duplicates.
Testing with mock data that differs from production: Use realistic amounts, customer data, and metadata in your tests.
Practice Questions
What test card should you use for a successful payment? 4242 4242 4242 4242 (always succeeds without authentication).
How do you test 3D Secure authentication? Use the card 4000 0025 0000 3155. The PaymentIntent will return requires_action status.
How do you test webhook events? Use the Stripe CLI: stripe trigger event.type or stripe listen to forward live events.
What test card triggers a declined payment? 4000 0000 0000 0002 (generic decline).
Challenge: Write a comprehensive test suite that tests all Stripe payment scenarios including success, decline, 3DS, insufficient funds, and processing error.
FAQ
Mini Project
Create a test runner that simulates all common payment scenarios using test cards and verifies the expected behavior.
import json
def run_tests():
test_cases = [
("4242424242424242", "succeeded", "Basic card payment"),
("4000000000000002", "declined", "Card declined"),
("4000002500003155", "requires_action", "3D Secure required"),
("4000000000000119", "declined", "Insufficient funds"),
("4000000000009989", "failed", "Processing error"),
]
passed = 0
for card, expected, scenario in test_cases:
result = json.dumps({"card": f"{card[:4]}...{card[-4:]}", "scenario": scenario, "expected": expected, "result": "simulated"})
passed += 1
print(f"[PASS] {scenario:<25s} | {card[:4]}...{card[-4:]}")
print(f"\n{passed}/{len(test_cases)} tests passed")
run_tests()
What's Next
Next: Stripe CLI for command-line tools.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro