Async Stripe

Testing

Tools and techniques for testing Stripe integrations

Testing Stripe integrations can be challenging. This guide covers the tools and techniques available for testing your Stripe integration without affecting production data or waiting for real-time events.

Testing with stripe-mock

For fast, offline testing without hitting the real Stripe API, you can use stripe-mock, Stripe's official API mocking server. Point your client to the mock server using the .url() method:

use stripe::Client;

// Start stripe-mock on port 12111
// docker run -p 12111:12111 stripe/stripe-mock

let client = Client::builder("sk_test_123")
    .url("http://localhost:12111")
    .build();

// This request will hit stripe-mock instead of the real API
let customer = Customer::create(&client, CreateCustomer::new()).send().await?;

stripe-mock provides realistic API responses but doesn't maintain state. It's ideal for integration tests that verify request formatting and response parsing without side effects.

Benefits of stripe-mock

  • Fast: No network latency
  • Offline: Works without internet connection
  • Deterministic: Same inputs always produce same outputs
  • Free: No API usage counted against your account
  • Safe: No risk of accidental charges or data changes

Running stripe-mock

# Using Docker (recommended)
docker run -p 12111:12111 stripe/stripe-mock

# Or install directly
go install github.com/stripe/stripe-mock@latest
stripe-mock -http-port 12111

stripe-mock is for testing only. Always use the real Stripe API in production.

Time Travel with Test Clocks

Testing subscription logic that spans months or years is difficult in real-time. async-stripe supports Test Clocks, allowing you to simulate the passage of time for customers without waiting.

Creating a Test Clock

Create a test clock frozen at a specific time (Unix timestamp):

let test_clock_1 = stripe::TestHelpersTestClock::create(
    &client,
    &CreateTestClock { frozen_time: timestamp as i64, name: "Example test clock 1" },
)
.await
.unwrap();

assert_eq!(test_clock_1.status, Some(TestHelpersTestClockStatus::Ready));
println!("created a test clock at https://dashboard.stripe.com/test/billing/subscriptions/test-clocks/{}", test_clock_1.id);

Advancing Time

Once you have a test clock, you can advance it to trigger time-based events like subscription renewals:

let new_timestamp = timestamp + (60 * 60 * 60);
let mut test_clock_1 = stripe::TestHelpersTestClock::advance(
    &client,
    &test_clock_1.id,
    &AdvanceTestClock { frozen_time: new_timestamp as i64 },
)
.await
.unwrap();
assert_eq!(test_clock_1.status, Some(TestHelpersTestClockStatus::Advancing));
println!("advancing test clock {} to {}", test_clock_1.id, new_timestamp);

Advancing a test clock is an asynchronous operation on Stripe's side. You can poll the status to wait for completion:

while test_clock_1.status == Some(TestHelpersTestClockStatus::Advancing) {
    println!("test clock {} is still advancing...", test_clock_1.id);
    sleep(Duration::from_secs(1)).await;

    test_clock_1 =
        stripe::TestHelpersTestClock::retrieve(&client, &test_clock_1.id).await.unwrap();
}
println!("test clock {} is now on status {}", test_clock_1.id, test_clock_1.status.unwrap());

What Test Clocks Affect

Test clocks control the timing for:

  • Subscription billing cycles - Trigger renewals without waiting
  • Trial periods - Fast-forward through trial expirations
  • Invoice finalization - Control when invoices are created and charged
  • Dunning - Test retry logic for failed payments
  • Prorations - Verify proration calculations when changing plans

Test clocks only work in test mode. All objects created with a test clock will be deleted when the clock is deleted.

Best Practices

Delete test clocks after testing to clean up test data:

let deleted_test_clock_1 =
    stripe::TestHelpersTestClock::delete(&client, &test_clock_1.id).await.unwrap();
assert!(deleted_test_clock_1.deleted);
println!("delete test clock {}", deleted_test_clock_1.id);

Use descriptive names to identify which test created which clock - the example uses "Example test clock 1" but in real tests you'd use something like "test_annual_subscription_renewal".

Advance time incrementally to observe state changes at each step rather than jumping too far ahead at once.

For more details, see the Stripe Test Clocks documentation.

Have feedback? Let us know here