Skip to content

Testing Stripe — Test Cards and Payment Scenarios

DodaTech Updated 2026-06-28 4 min read

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

  1. Testing only the success path: Test declines, 3D Secure, expired cards, and insufficient funds to ensure your error handling works.

  2. Using test cards in production: Test cards succeed in test mode but fail in live mode. Always verify you are in test mode.

  3. Not testing webhook scenarios: Trigger webhook events with the Stripe CLI to verify your webhook handler works correctly.

  4. Forgetting to test idempotency: Send the same request twice to ensure your system handles duplicates.

  5. Testing with mock data that differs from production: Use realistic amounts, customer data, and metadata in your tests.

Practice Questions

  1. What test card should you use for a successful payment? 4242 4242 4242 4242 (always succeeds without authentication).

  2. How do you test 3D Secure authentication? Use the card 4000 0025 0000 3155. The PaymentIntent will return requires_action status.

  3. How do you test webhook events? Use the Stripe CLI: stripe trigger event.type or stripe listen to forward live events.

  4. What test card triggers a declined payment? 4000 0000 0000 0002 (generic decline).

  5. Challenge: Write a comprehensive test suite that tests all Stripe payment scenarios including success, decline, 3DS, insufficient funds, and processing error.

FAQ

Can I create custom test cards?

No, Stripe provides specific test card numbers. You cannot create custom test card numbers.

Do test cards work in live mode?

No. Test cards only work in test mode. They will be declined in live mode.

How do I test refunds?

Create a test charge with a test card, then call the refund API. Refunds work identically in test mode.

Can I test Stripe Connect in test mode?

Yes. Test mode supports all Stripe Connect functionality with test accounts.

How do I reset test data?

Stripe automatically resets test mode data periodically. Use the Stripe CLI or Dashboard to manage test data.

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