Preface
In this series, we’ve explored some key highlights for a modest implementation of a Stripe integration that brings together the capabilities of Stripe Connect and Stripe Billing for a fictitious business, Oasis Hubs. The business provides customers access to unique private and commercial workspaces that can be conveniently booked for a given number of hours. Customers will be able to choose between different subscription tiers that will give them access to various workspace listings (hubs) which have been provided by the service vendors (hosts). Hosts will sign up to the platform to provide details of their available workspaces, and get paid monthly based on the number of hours booked for their workspace.
In this last (maybe?) article, we will cover validating subscription logic with test clocks.
We should test this
In the software industry, and also many others, it is important that we thoroughly test our products before releasing them to the public. Unit tests, integration tests, A/B tests, performance tests, and many more aim to verify and set the quality bar so we can ship with confidence. However, with the way we test software today, there is usually an expectation that when a suite of tests is run we should receive results that we can inspect within a relatively short amount of time. Depending on the type, tests may take a few minutes or even as long as a few hours.
When building support for recurring payments such as a subscription or a payment plan that might have a billing cycle spanning weeks or months, how can we verify our integration is working correctly? Waiting in real-time for one iteration of a billing cycle is far from being a viable option. While running unit tests against the various components of our software in isolation is possible, we still need the ability to run through more realistic scenarios; especially when integrating with an external payments service like Stripe.
Time traveling with Test Clocks
Since no one on the planet, that we know of, has successfully invented a time machine we are going to need to look for another alternative for simulating recurring billing cycles. Within the Oasis Hubs Stripe account, in test mode, we can make use of a feature called test clocks. Test clocks will allow us to simulate the forward movement of time in Stripe objects; like subscriptions, quotes, and customers. Once the time is adjusted, any time sensitive webhook events will get triggered and we will be able to handle those events in the action methods of the WebhookController.
We’ve discussed handling webhooks and the WebhookController on various occasions in previous articles of this series. //ADD LINK
Test clocks can be used to validate the logic for time based scenarios in your Stripe integration such as trial periods, prorations, subscription payments, upgrades or renewals. Creating and using a test clock follows a similar pattern to the other objects we’ve created in Stripe. In this article we’ll be using the Stripe .NET library, but there are other options available such as the Stripe CLI, the Stripe Dashboard, or one of the other language SDKs. This means that instead of waiting for weeks or months to test our recurring payment integration, we can run a simulation that would only take a few minutes.
Before we can start a simulation, we need to create a new test clock and set its initial time using the “FrozenTime” property. We have to specify the time as a Unix Epoch timestamp which can be either in the past or in the future. Once the TestClock object is created it can only be moved forward in time.
var tcCreateOptions = new TestClockCreateOptions{
Name = $"Subscription Clock ({name})",
FrozenTime = DateTimeOffset.UtcNow.DateTime
};
var testClockService = new TestClockService();
var newTestClock = await testClockService.CreateAsync(tcCreateOptions);
Test clocks can be attached to different objects in Stripe such as Customers, Subscriptions or even quotes. The snippet above, from the Oasis Hubs fake data generator, creates a new Customer object and associates it with a test clock. Existing objects in a Stripe account cannot be later updated to use a test clock. This has to be specified at the time of creation.
var ccOptions = new CustomerCreateOptions{
Name = name,
Email = email,
Description = "Faker User Account",
PaymentMethod = "pm_card_visa",
TestClock = newTestClock.Id,
InvoiceSettings = new CustomerInvoiceSettingsOptions
{
DefaultPaymentMethod = "pm_card_visa"
}
};
var newCustomer = await customerService.CreateAsync(ccOptions);
Once this is done, other relevant Stripe objects linked with this Customer will also be associated with the test clock. That means when a Subscription or Invoice object is created for this Customer, we don’t have to pass the test clock Id along to them. This behavior applies to objects created via one of Stripe's hosted payment forms or if the objects created directly via the Stripe API.
var options = new SubscriptionCreateOptions {
Customer = newCustomer.Id,
Items = new List<SubscriptionItemOptions> {
new SubscriptionItemOptions {Price = "my_price_id"}
}
};
var subscriptionService = new SubscriptionService();
await subscriptionService.CreateAsync(options);
Inside of the Stripe Dashboard, any Customer objects created in test mode that are associated with a test clock will have a clock item next to their record.
If we dig deeper into the Customer details, you will notice that we now have the option to to “Advance time” using that test clock.
Test clocks can be advanced using the UI in Stripe Dashboard and also from your application code using one of the SDKs.
However, test clocks have limitations. Test clocks can only be advanced by two intervals at a time based on the shortest subscription interval of associated items. For example, if the test clock is associated with a monthly subscription, it can only advance up to two months at a time. If there are multiple associated subscription cycles, then the clock can be advanced up to two internals of the shortest cycle.
Limitations of Time Traveling
Before we start setting up and processing complex scenarios using test clocks. For each test clock created, there can be only three attached Customers, three attached Subscriptions, and ten Quotes. It is possible to create multiple test clocks that have their own unique name, initial time, and collection of associated Stripe objects. To learn more about the limitations of test clocks, take a look at documentation links referenced below.
Regardless of the limitations, this feature enables the possibility of some interesting test cases that you can integrate into your test automation and CI/DI pipelines.
References
Stay connected with Stripe
You can also stay up-to-date with Stripe developer updates on the following platforms:
📣 Follow @StripeDev on Twitter.
📺 Subscribe to our YouTube channel.
💬 Join the official Discord server.
📧 Sign up for the Developer Digest.
Top comments (0)